JavaWeb课程系列

第17章文件上传下载

1.文件上传

1.1提出问题

客户需要将自己的文件上传给服务器怎么处理?

文件上传的时候是怎样提交给服务器的?

 

答:我们可以使用multipart/form-data表单处理文件上传

         文件的上传是以流的形式提交给服务器的

1.2文件上传步骤

文件上传我们需要用到两个包。commons-fileupload-1.3.1.jar、commons-io-2.4.jar。

所以先导入包。然后进行文件上传测试

文件上传步骤:

1)修改表单enctype值为multipart/form-data,并且method=post

<form action="upload" method="post" enctype="multipart/form-data">

                   <input type="file" name="file">

                   <input type="submit">

</form>

2)创建文件上传请求解析器

在doPost方法中创建ServletFileUpload对象,并传入DiskFileItemFactory工厂对象

DiskFileItemFactory factory = new DiskFileItemFactory();

                   ServletFileUpload fileUpload = new ServletFileUpload(factory);

3)解析并上传文件

解析上传文件请求

List<FileItem> list = fileUpload.parseRequest(request);

                            for(FileItem f : list){

                                     if(f.isFormField()){//普通表单项

 

                                     }else{ //文件表单项

                                               String name = f.getName();

                                               System.out.println(name);

                                               f.write(new File("D:/"+name));

                                     }

}

 

注意事项:

①、当文件上传表单的文件项未选择文件时,文件大小为0,应该做判断,当文件大小为0则不进行上传

②、使用fileItem.getName()获取文件名。在火狐谷歌下,为文件的名字。在ie下为文件的路径,因此要获取文件名需要进行处理

③、使用fileItem.getString(“utf-8”),获取文件普通表单项的值

 

完整的文件上传代码:

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

                   // 1、创建fileItem工厂

                   DiskFileItemFactory factory = new DiskFileItemFactory();

                   // 2、创建文件上传对象

                   ServletFileUpload fileUpload = new ServletFileUpload(factory);

                   // 3、解析文件上传请求

                   try {

                            List<FileItem> list = fileUpload.parseRequest(request);

                            // 4、遍历解析出的每个FileItem文件

                            for (FileItem f : list) {

                                     // 这是普通表单项

                                     if (f.isFormField()) {

                                               // 表单项的name值

                                               String fieldName = f.getFieldName();

                                               // 表单项value,使用编码取得中文

                                               String fieldValue = f.getString("utf-8");

                                               System.out.println(fieldName + ":" + fieldValue);

 

                                     // 表示文件表单项

                                     } else {

                                               //获取文件大小,有可能并没有上传文件

                                               long size = f.getSize();

                                               if(size == 0){

                                                        continue;

                                               }

 

                                               // 获取文件名字

                                               String name = f.getName();

                                               // ie下是全路径,火狐谷歌为文件名,需要不同处理

                                               if (name.contains("\\")) {

                                                        name = name.substring(name.lastIndexOf("\\") + 1);

                                               }

 

                                               //获取文件保存的服务端路径

                                               String realPath = request.getServletContext().getRealPath("/upload");

                                               File file = new File(realPath);

                                               if(!file.exists()){

                                                        file.mkdirs();

                                               }

                                               //生成一个唯一不重复的文件名

                                               name = UUID.randomUUID().toString().replace("-", "")+"-"+name;

                                               //将文件内容写入

                                               f.write(new File(realPath+"/"+name));

                                     }

                            }

                   } catch (FileUploadException e) {

                            e.printStackTrace();

                   } catch (Exception e) {

                            e.printStackTrace();

                   }

                   response.setContentType("text/html;charset=UTF-8");

                   response.getWriter().write("上传完成!");

         }

 

其他注意:

fileUpload可以来限制文件的大小

                   //设置当文件的大小为50KB

                   //fileUpload.setFileSizeMax(1024*50);

 

                   //设置多个文件的总大小为150KB

                   fileUpload.setSizeMax(1024*150);

 

当文件超出大小限制的时候会抛出异常,增加catch子句来处理

catch (SizeLimitExceededException e) {

                            response.setContentType("text/html;charset=UTF-8");

                            response.getWriter().write("文件大小超出限制");

                            return;

                   }

 

原理:

分析文件上传的请求我们会发现,文件上传的时候request的body会增加一个分界符,分界符用来分割正常的表单域和文件表单域,文件的内容在分界符的中间,以流的形式传递,文件上传的request请求如下:

以上是请求头;

 

下面是请求体携带的数据: