JavaWeb之上传文件
一、文件上传对页面的要求
1,必须使用表单
2,表单的method必须是POST,而不是GET
3,表单的enctype必须是multipart/form-data;
4,在表单中添加file表单字段,即<input type=”file”…/>
即:
1
2 3 4 5 6 7 |
<form
action
=
"${pageContext.request.contextPath }/FileUploadServlet"
method
=
"post"
enctype
=
"multipart/form-data"
>
用户名: <input type = "text" name = "username" /><br/> 文件1: <input type = "file" name = "file1" /><br/> 文件2: <input type = "file" name = "file2" /><br/> <input type = "submit" value = "提交" /> </form> |
二、对比文件上传表单和普通文本表单的区别
l 文件上传表单的enctype=”multipart/form-data”,表示多部件表单数据;
l 普通文本表单可以不设置enctype属性:
Ø 当method=”post”时,enctype的默认值为application/x-www-form-urlencoded,表示使用url编码正文;
当method=”get”时,enctype的默认值为null,没有正文,所以就不需要enctype了。
三、文件上传表单的测试
1
2 3 4 5 6 7 |
<form
action
=
"${pageContext.request.contextPath }/FileUploadServlet"
method
=
"post"
enctype
=
"multipart/form-data"
>
用户名: <input type = "text" name = "username" /><br/> 文件1: <input type = "file" name = "file1" /><br/> 文件2: <input type = "file" name = "file2" /><br/> <input type = "submit" value = "提交" /> </form> |
文本字段的头信息中只包含一条头信息,即Content-Disposition,这个头信息的值有两个部分,第一部分是固定的,即form-data,第二部分为字段的名称。在空行后面就是正文部分了,正文部分就是在文本框中填写的内容。
文件字段的头信息中包含两条头信息,Content-Disposition和Content-Type。Content-Disposition中多出一个filename,它指定的是上传的文件名称。而Content-Type指定的是上传文件的类型。文件字段的正文部分就是文件的内容。
四、文件上传对Servlet的要求
首先我们要肯定一点,文件上传表单的数据也是被封装到request对象中的。
request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
这时可以使用request的getInputStream()方法获取ServletInputStream对象,它是InputStream的子类,这个ServletInputStream对象对应整个表单的正文部分(从第一个分隔线开始,到最后),这说明我们需要的解析流中的数据。当然解析它是很麻烦的一件事情,而Apache已经帮我们提供了解析它的工具:commons-fileupload。
五、commons-fileupload介绍
为什么使用fileupload:
上传文件的要求比较多,需要记一下:
l 必须是POST表单;
l 表单的enctype必须是multipart/form-data;
l 在表单中添加file表单字段,即<input type=”file”…/>
Servlet的要求:
l 不能再使用request.getParameter()来获取表单数据;
l 可以使用request.getInputStream()得到所有的表单数据,而不是一个表单项的数据;
l 这说明不使用fileupload,我们需要自己来对request.getInputStream()的内容进行解析!!!
1,fileupload概述
fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。
fileupload组件需要的JAR包有:
l commons-fileupload.jar,核心包;
l commons-io.jar,依赖包。
2,fileupload简单应用
fileupload的核心类有:DiskFileItemFactory,ServletFileUpload,FileItem
使用步骤如下:
1. 创建工厂类DiskFileItemFactory对象:DiskFileItemFactoryfactory = new DiskFileItemFactory()
2. 使用工厂创建解析器对象:ServletFileUpload fileUpload = new ServletFileUpload(factory)
3. 使用解析器来解析request对象:List<FileItem>list = fileUpload.parseRequest(request)
介绍FileItem类,它才是我们最终要的结果。一个FileItem对象对应一个表单项(表单字段)。一个表单中存在文件字段和普通字段,可以使用FileItem类的isFormField()方法来判断表单字段是否为普通字段,如果不是普通字段,那么就是文件字段了。
l String getName():获取文件字段的文件名称;
l String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
l String getFieldName():获取字段名称,例如:<inputtype=”text” name=”username”/>,返回的是username;
l String getContentType():获取上传的文件的类型,例如:text/plain。
l int getSize():获取上传文件的大小;
l boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
l InputStream getInputStream():获取上传文件对应的输入流;
l void write(File):把上传的文件保存到指定文件中。
六、简单上传示例
第一步:
完成index.jsp,只需要一个表单。注意表单必须是post的,而且enctype必须是mulitpart/form-data的。
1
2 3 4 5 6 |
<form
action
=
"${pageContext.request.contextPath }/FileUploadServlet"
method
=
"post"
enctype
=
"multipart/form-data"
>
用户名: <input type = "text" name = "username" /><br/> 文件1: <input type = "file" name = "file1" /><br/> <input type = "submit" value = "提交" /> </form> |
第二步:
完成FileUploadServlet
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { // 因为要使用response打印,所以设置其编码 response.setContentType( "text/html;charset=utf-8" ); // 创建工厂 DiskFileItemFactory dfif = new DiskFileItemFactory(); // 使用工厂创建解析器对象 ServletFileUpload fileUpload = new ServletFileUpload(dfif); try { // 使用解析器对象解析request,得到FileItem列表 List < FileItem > list = fileUpload.parseRequest(request); // 遍历所有表单项 for(FileItem fileItem : list) { // 如果当前表单项为普通表单项 if(fileItem.isFormField()) { // 获取当前表单项的字段名称 String fieldName = fileItem.getFieldName(); // 如果当前表单项的字段名为username if(fieldName.equals( "username" )) { // 打印当前表单项的内容,即用户在username表单项中输入的内容 response.getWriter().print( "用户名:" + fileItem.getString() + "<br/>" ); } } else { // 如果当前表单项不是普通表单项,说明就是文件字段 String name = fileItem.getName(); // 获取上传文件的名称 // 如果上传的文件名称为空,即没有指定上传文件 if(name == null || name.isEmpty()) { continue; } // 获取真实路径,对应${项目目录} / uploads,当然,这个目录必须存在 String savepath = this.getServletContext().getRealPath( "/uploads" ); // 通过uploads目录和文件名称来创建File对象 File file = new File(savepath, name); // 把上传文件保存到指定位置 fileItem.write(file); // 打印上传文件的名称 response.getWriter().print( "上传文件名:" + name + "<br/>" ); // 打印上传文件的大小 response.getWriter().print( "上传文件大小:" + fileItem.getSize() + "<br/>" ); // 打印上传文件的类型 response.getWriter().print( "上传文件类型:" + fileItem.getContentType() + "<br/>" ); } } } catch (Exception e) { throw new ServletException(e); } } |