文件上传和下载

一、文件上传需要注意的事情

1、必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。

2、必须把form的enctype属值设为multipart/form-data.设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。

 

 

二、传统的方式获取表单提交的数据

 

 

 1     public void doGet(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String name = request.getParameter("username");
 4         
 5 /*        //null  当enctype="multipart/form-data" 不能用传统的方式获取数据
 6         System.out.println(name);
 7         */
 8         
 9         InputStream in = request.getInputStream();
10         int len = 0;
11         byte buffer[] = new byte[1024];
12         while((len=in.read(buffer))>0){
13             System.out.println(new String(buffer,0,len));
14         }
15         
16         /*------WebKitFormBoundary6hYLK68ivBSHvVww
17         Content-Disposition: form-data; name="username"
18 
19         name
20         ------WebKitFormBoundary6hYLK68ivBSHvVww
21         Content-Disposition: form-data; name="file1"; filename="aa.txt"
22         Content-Type: text/plain
23 
24         bbbbbb
25         ------WebKitFormBoundary6hYLK68ivBSHvVww
26         Content-Disposition: form-data; name="file2"; filename="bb.txt"
27         Content-Type: text/plain
28 
29         bbbb
30         ------WebKitFormBoundary6hYLK68ivBSHvVww--*/
31         
32         //由此可见, 当enctype="multipart/form-data" 用传统的方式无法解析
33     }
34     
35     public void doPost(HttpServletRequest request, HttpServletResponse response)
36             throws ServletException, IOException {
37         doGet(request, response);
38     }
39 
40 }

 

 

 

三、Commons-fileupload组件实现文件上传

fileupload工作流程图:

 

Commons-fileupload依赖的jar包:Commons-fileupload和commons-io

 

 

 1 //处理上传数据
 2 public class UploadServlet1 extends HttpServlet {
 3 
 4     public void doGet(HttpServletRequest request, HttpServletResponse response)
 5             throws ServletException, IOException {
 6         try{
 7             //创建工厂对象
 8             DiskFileItemFactory factory = new DiskFileItemFactory();
 9             ServletFileUpload upload = new ServletFileUpload(factory);
10             //解析
11             List<FileItem>list = upload.parseRequest(request);
12             for(FileItem item : list){
13                 if(item.isFormField()){//普通输入项
14                     String inputName = item.getFieldName();
15                     String inputValue = item.getString();
16                     System.out.println(inputName+"="+inputValue);
17                 }else{
18                     //代表item封装的是上传文件
19                     String fileName = item.getName().substring(item.getName().lastIndexOf("\\")+1);
20                     InputStream in = item.getInputStream();
21                     FileOutputStream out = new FileOutputStream("d:\\"+fileName);
22                     int len = 0;
23                     byte buffer[] = new byte[1024];
24                     while((len=in.read(buffer))>0){
25                         out.write(buffer,0, len);
26                     }
27                     in.close();
28                     out.close();
29                 }
30             }
31             
32         }catch(Exception e){
33             throw new RuntimeException();
34         }
35     }
36         
37     
38     public void doPost(HttpServletRequest request, HttpServletResponse response)
39             throws ServletException, IOException {
40         doGet(request, response);
41     }
42 
43 }

 

 

四、文件上传需要注意的问题

1、上传文件的中文乱码

解决上传文件的乱码

DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");

 

 

解决普通输入项的乱码(注意,表单类型为multipart/form-data的时候,设置request的编码是无效的

String inputValue = item.getString("UTF-8");或

String inputValue = item.getString();
inputValue = new String(inputValue.getBytes("iso8859-1"), "UTF-8");

 

 

2、处理表单时先判断表单的类型

 

1             if(!upload.isMultipartContent(request)){//表单不是multipart/form-data类型按传统方式获取数据
2                 String username = request.getParameter("username");
3                 return;
4             }

 

 

 

 

3、设置解析器缓冲区的大小,以及临时文件的删除

//创建工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();

//设置缓冲区大小
factory.setSizeThreshold(1024*1024);

//设置临时目录
factory.setRepository(new File(this.getServletContext().getRealPath("/temp")));

 

临时文件的删除:在程序中处理完上传文件后,一定要记得调用item.delete()方法,以删除临时文件,而且是在流关闭后再删除

in.close();
out.close();

//删除临时文件目录
item.delete();

 

 

4、在做上传系统时,千万要注意上传文件的保存目录,这个上传文件的保存目录绝对不能让外界直接访问到。应该放在WEB-INF目录下

 

 

5、限制上传文件的类型

List types = Arrays.asList("jpg","gif","avi","txt");

 

String ext = filename.substring(filename.lastIndexOf(".")+1);
if(!types.contains(ext)){
request.setAttribute("message", "本系统不支持" + ext + "这种类型");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}

 

  

 

6、限制上传文件的大小

upload.setFileSizeMax(1024*1024*5);

调用解析器的setFileSizeMax(1024*1024*5);就可以限制上传文件的大小,如果上传文件超出限制,则解析器会抛FileUploadBase.FileSizeLimitExceededException异常,程序员通过是否抓到这个异常,进而就可以给用户友好提示。

 

7、判断空的上传输入项

String fileName = item.getName().substring(item.getName().lastIndexOf("\\")+1);

if(fileName==null || fileName.trim().equals("")){
continue;
}

 

8、为避免上传文件的覆盖,程序在保存上传文件时,要为每一个文件生成一个唯一的文件名

public static String generateFileName(String fileName){
return UUID.randomUUID()+"_"+fileName;
}

 

9、为避免在一个文件夹下面保存超过1000个文件,影响文件访问性能,程序应该把上传文件打散后存储。

 1     public String generateSavePath(String path,String filename){
 2         int hashcode = filename.hashCode();  //121221
 3         int dir1 = hashcode&15;
 4         int dir2 = (hashcode>>4)&0xf;
 5         
 6         String savepath = path + File.separator + dir1 + File.separator + dir2;
 7         File file = new File(savepath);
 8         if(!file.exists()){
 9             file.mkdirs();
10         }
11         return savepath;
12     }

 

 

 10、监听上传进度

1     ServletFileUpload upload = new ServletFileUpload(factory);
2             upload.setProgressListener(new ProgressListener(){
3                 public void update(long pBytesRead, long pContentLength, int pItems) {
4                     System.out.println("当前已解析:" + pBytesRead);
5                 }
6             });

 

 

 

  1 import java.io.File;
  2 import java.io.FileOutputStream;
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.util.Arrays;
  6 import java.util.List;
  7 import java.util.UUID;
  8 
  9 import javax.servlet.ServletException;
 10 import javax.servlet.http.HttpServlet;
 11 import javax.servlet.http.HttpServletRequest;
 12 import javax.servlet.http.HttpServletResponse;
 13 
 14 import org.apache.commons.fileupload.FileItem;
 15 import org.apache.commons.fileupload.FileUploadBase;
 16 import org.apache.commons.fileupload.ProgressListener;
 17 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 18 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 19 
 20 public class UploadServlet extends HttpServlet {
 21 
 22     public void doGet(HttpServletRequest request, HttpServletResponse response)
 23             throws ServletException, IOException {
 24         
 25         List types = Arrays.asList("jpg","gif","avi","txt");
 26         
 27         try{
 28             DiskFileItemFactory factory = new DiskFileItemFactory();  //10k
 29             factory.setSizeThreshold(1024*1024);
 30             factory.setRepository(new File(this.getServletContext().getRealPath("/temp")));
 31             
 32             ServletFileUpload upload = new ServletFileUpload(factory);
 33             upload.setProgressListener(new ProgressListener(){
 34                 public void update(long pBytesRead, long pContentLength, int pItems) {
 35                     System.out.println("当前已解析:" + pBytesRead);
 36                 }
 37             });
 38             
 39             upload.setFileSizeMax(1024*1024*5);
 40             if(!upload.isMultipartContent(request)){
 41                 //按照传统方式获取表单数据
 42                 request.getParameter("username");
 43                 return;
 44             }
 45             upload.setHeaderEncoding("UTF-8");
 46             List<FileItem> list = upload.parseRequest(request);
 47             
 48             for(FileItem item : list){
 49                 if(item.isFormField()){
 50                     //为普通输入项
 51                     String inputName = item.getFieldName();
 52                     String inputValue = item.getString("UTF-8");
 53                     //inputValue = new String(inputValue.getBytes("iso8859-1"),"UTF-8");
 54                     System.out.println(inputName + "="  + inputValue);
 55                 }else{
 56                     String filename = item.getName().substring(item.getName().lastIndexOf("\\")+1);  //""
 57                     if(filename==null || filename.trim().equals("")){
 58                         continue;
 59                     }
 60                     
 61                     /*String ext = filename.substring(filename.lastIndexOf(".")+1);
 62                     if(!types.contains(ext)){
 63                         request.setAttribute("message", "本系统不支持" + ext + "这种类型");
 64                         request.getRequestDispatcher("/message.jsp").forward(request, response);
 65                         return;
 66                     }*/
 67                     InputStream in = item.getInputStream();
 68                     int len = 0;
 69                     byte buffer[] = new byte[1024];
 70                     String saveFileName = generateFileName(filename);
 71                     String savepath = generateSavePath(this.getServletContext().getRealPath("/WEB-INF/upload"),saveFileName);
 72                     FileOutputStream out = new FileOutputStream(savepath + File.separator + saveFileName);
 73                     while((len=in.read(buffer))>0){
 74                         out.write(buffer, 0, len);
 75                     }
 76                     in.close();
 77                     out.close();
 78                     item.delete();  //删除临时文件
 79                 }
 80             }
 81         }catch (FileUploadBase.FileSizeLimitExceededException e) {
 82             request.setAttribute("message", "文件大小不能超过5m");
 83             request.getRequestDispatcher("/message.jsp").forward(request, response);
 84             return;
 85         }catch (Exception e) {
 86             throw new RuntimeException(e);
 87         }
 88         request.setAttribute("message", "上传成功!!");
 89         request.getRequestDispatcher("/message.jsp").forward(request, response);
 90     }
 91     
 92     //
 93     public String generateSavePath(String path,String filename){
 94         int hashcode = filename.hashCode();  //121221
 95         int dir1 = hashcode&15;
 96         int dir2 = (hashcode>>4)&0xf;
 97         
 98         String savepath = path + File.separator + dir1 + File.separator + dir2;
 99         File file = new File(savepath);
100         if(!file.exists()){
101             file.mkdirs();
102         }
103         return savepath;
104     }
105     
106     public String generateFileName(String filename){
107         //83434-83u483-934934
108         return UUID.randomUUID().toString() + "_" + filename;
109     }
110 
111     public void doPost(HttpServletRequest request, HttpServletResponse response)
112             throws ServletException, IOException {
113         doGet(request, response);
114     }
115 
116 }

 

 三、在web页面动态添加输入项

 

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6     <title>My JSP 'upload2.jsp' starting page</title>
 7   </head>
 8   
 9   <script type="text/javascript">
10           function addfile(){
11               var files = document.getElementById("files");
12               
13               var input = document.createElement("input");
14               input.type='file';
15               input.name='file';
16               
17               var btn = document.createElement("input");
18               btn.type = 'button';
19               btn.value = '删除';
20               btn.onclick = function del(){
21                   this.parentNode.parentNode.removeChild(this.parentNode);
22               }
23               
24               var div = document.createElement("div");
25               div.appendChild(input);
26               div.appendChild(btn);
27               
28               files.appendChild(div);
29           }
30       
31   </script>
32   
33   <body>
34     
35     <form action="/day18/servlet/UploadServlet3" enctype="multipart/form-data" method="post">
36     
37     <table>
38         <tr>
39             <td>上传用户</td>
40             <td>
41                 <input type="text" name="username">
42             </td>
43         </tr>
44         
45         <tr>
46             <td>上传文件</td>
47             <td>
48                 <input type="button" value="添加上传文件" onclick="addfile()">
49             </td>
50         </tr>
51         
52         <tr>
53             <td></td>
54             <td>
55                 <div id="files"></div>
56             </td>
57         </tr>
58         
59         <tr>
60             <td></td>
61             <td>
62                 <input type="submit" value="上传">
63             </td>
64         </tr>
65     
66     </table>
67     </form>
68     
69     
70   </body>
71 </html>

 

posted @ 2018-06-14 22:32  牛穿疯  阅读(308)  评论(0编辑  收藏  举报
levels of contents