servlet文件上传技术

Java文件上传的技术有很多,本文主要讲的是java开发过程中,利用form表单上传文件。这一过程主要是利用http协议,向服务器端发出一个POST请求,上传的文件主要放在http请求报文的主体部分,同时,表单中可能还会传递其他信息。下面的代码是一个jsp的表单,该表单除了要传递文件外,还需要传递关于该文件的文本描述信息。enctype表示这个表单采取的编码格式,其默认值为application/x-www-form-urlencoded。当enctype为默认值时,表单数据以键值对的形式编码,如采用get方式提交表单,则表单数据会以key1=value1&key2=value2的形式加在URL末尾;如采用post方式提交,则表单信息会以键值对的形式存放在报文主体中。这里的enctype的值为multipart/form-data,表示表单内容将被编码成一条信息,而表单中的每个input对应一条信息的一个部分,每个部分用boundary=*******************分割(星号部分由浏览器自动生成)。

	<form action="upload" method="POST" enctype="multipart/form-data">
		<tr>
			<input type="file" name="file">选择文件
			</input>
		</tr>
		<tr>
			<input type="text" name="description"></input>
		</tr>
		<tr>
			<input type="submit" value="上传"></input>
		</tr>
	</form>

后台部分

后台实现文件上传的方法很多。

1.Servlet

这里采用sevlet3.0里面对这个问题的实现,重写了HttpServlet的继承类的doPost方法。

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
		req.setCharacterEncoding("utf-8");
		List<Part> parts=(List<Part>) req.getParts();
		for(Part part:parts){
			if(part.getName().equals("file")){
				part.write("/"+getFileName(part));				
			}
		}
		resp.setContentType("text/html");
		
		PrintWriter pw=resp.getWriter();
		pw.print("ok");
		
		
	}
这个地方出现了两个问题,第一个问题,上传文件后,返回的状态:

这个方法包含语句super.doPost(),查看父类的doPost方法:

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if(protocol.endsWith("1.1"))
            resp.sendError(405, msg);
        else
            resp.sendError(400, msg);
    }
显然,response返回的是父类中的信息,虽然子类中也包含一些信息,但并没有展现出来。接着,在重写的servlet类的doPost方法中调用response的方法isCommitted(),结果返回true,也就是说response已经返回,这样就会造成super.doPost()方法后面写入response的信息并没有被返回到client。所以,接下来就去掉这里面对父类该方法的调用。

但此时又出现的另一个问题,parts集合为null,Part类型的对象即对应报文中携带的input中的信息,解决这个问题的方法为添加注解@MultipartConfig()。

@MultipartConfig()
public class Upload extends HttpServlet {
上面代码中的req.getName()只能得到input中的name属性的值,并不是传输的文件的文件名,为了得到文件的文件名,可以利用谷歌浏览器对http的请求报文进行分析,下面只展示了报文的主体部分,显然,每个部分都是用------WebKitFormBoundaryBITEzBfMWOPRBr4H进行了分割,分成了若干个part,下面的第一个part对应上传文件的那个input,其中Content-Disposition字段正好包含filename。另外这里面Content-Disposition和Content-Type都是包含在part首部的信息,这个地方上传的二进制文件(图片)并没有显示出来,但是下面一个part的内容显示出来了,我在输入框中输入了“这是描述信息”,这个可以理解为part的body部分。

------WebKitFormBoundaryBITEzBfMWOPRBr4H
Content-Disposition: form-data; name="file"; filename="Koala.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryBITEzBfMWOPRBr4H
Content-Disposition: form-data; name="description"

这是描述信息
------WebKitFormBoundaryBITEzBfMWOPRBr4H--
所以,可以提取出第一个part首部中Content-Disposition字段值,然后通过字符串操作获取filename的值。
private String getFileName(Part part){
		String contentDidposition=part.getHeader("Content-Disposition");
		String[] elements=contentDidposition.split(";");
		String filename=null;
		for(String elem:elements){
			if(elem.trim().startsWith("filename")){
				filename=elem.substring(elem.indexOf("=")+2, elem.length()-1);
			}
			
		}
		return filename;
		
	}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值