Java学习笔记(五):文件的上传和下载
- 文件上传原理
1、文件上传的前提: a、表单的method必须是post b、表单的enctype属性必须是multipart/form-data c、表单中提供input type=”file” <p align="center"> </p>
- 2、form表单的enctype属性
该属性的作用是用来告知服务器,请求正文内容的MIME类型的。相当于请求消息头Content-Type。
- enctype=application/x-www-form-urlencoded(Content-Type=application/x-www-form-urlencoded)默认值。
username=abc&password=123 服务器端:String vlaue = request.getParameter(String name)只能读取请求正文是application/x-www-form-urlencoded类型的数据。
- enctype=multipart/form-data(Content-Type=multipart/form-data)
- 利用第三方组件实现文件上传
1、apache的:commons-fileupload组件。
依赖:commons-io组件
2、开发主要的步骤
判断form是否是multipart/form-data类型的
解析请求内容 产生fileitem的工厂
对字段进行遍历 并处理上传字段,找一个存放的位置 创建存放路径
1 package com.itheima.servlet;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.util.ArrayList;
9 import java.util.List;
10
11 import javax.servlet.ServletException;
12 import javax.servlet.http.HttpServlet;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15
16 import org.apache.commons.fileupload.FileItem;
17 import org.apache.commons.fileupload.FileUploadException;
18 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
19 import org.apache.commons.fileupload.servlet.ServletFileUpload;
20 import org.apache.commons.io.FileUtils;
21 import org.apache.commons.io.FilenameUtils;
22 //借助commons-fileupload组件实现文件上传:简单版本
23 public class UploadServlet2 extends HttpServlet {
24
25 public void doGet(HttpServletRequest request, HttpServletResponse response)
26 throws ServletException, IOException {
27 //检测form是否是multipart/form-data类型的
28 boolean isMultipart = ServletFileUpload.isMultipartContent(request);
29 if(!isMultipart){
30 throw new RuntimeException("The form's enctype attribute value must be multipart/form-data");
31 }
32 //解析请求内容
33 DiskFileItemFactory factory = new DiskFileItemFactory();//产生FileItem的工厂
34 ServletFileUpload sfu = new ServletFileUpload(factory);
35 List<FileItem> items = new ArrayList<FileItem>();
36 try {
37 items = sfu.parseRequest(request);
38 } catch (FileUploadException e) {
39 throw new RuntimeException("解析请求失败");
40 }
41 //遍历:
42 for(FileItem item:items){
43 //处理普通字段
44 if(item.isFormField()){
45 processFormField(item);
46 }else{
47 //处理上传字段
48 processUploadField(item);
49 }
50 }
51 }
52
53 protected void processUploadField(FileItem item) {
54 try {
55 // InputStream in = item.getInputStream();
56 //找一个存放文件的位置;存放的文件名
57 String fileName = item.getName();//上传的文件的文件名 C:UserswzhtingDesktopa.txt a.txt(浏览器不同)
58 if(fileName!=null){
59 fileName = FilenameUtils.getName(fileName);
60 }
61 //存放路径
62 String realPath = getServletContext().getRealPath("/files");
63 File storeDirectory = new File(realPath);
64 if(!storeDirectory.exists()){
65 storeDirectory.mkdirs();
66 }
67 // OutputStream out = new FileOutputStream(new File(storeDirectory, fileName));
68 //
69 // int len = -1;
70 // byte b[] = new byte[1024];
71 // while((len=in.read(b))!=-1){
72 // out.write(b, 0, len);
73 // }
74 // in.close();
75 // out.close();
76
77 item.write(new File(storeDirectory, fileName));
78
79 } catch (Exception e) {
80 e.printStackTrace();
81 }
82 }
83
84 protected void processFormField(FileItem item) {
85 //打印到控制台
86 String fieldName = item.getFieldName();
87 String fieldValue = item.getString();
88 System.out.println(fieldName+"="+fieldValue);
89 }
90
91 public void doPost(HttpServletRequest request, HttpServletResponse response)
92 throws ServletException, IOException {
93 doGet(request, response);
94 }
95
96 }
- 上传过程中需要考虑的几个问题
1.保证服务器的安全 解决:把上传的文件放到用户访问不到的地方(放到WEB-INF目录下)
2.重名文件被覆盖<p align="center"> </p>
解决办法:把文件名弄成唯一即可。
a.txt———————–>UUID_a.txt
创建IdGenertor类,内有genGUID方法:
1 package com.itheima.util;
2
3 import java.math.BigInteger;
4 import java.util.Random;
5
6 public class IdGenertor {
7 public static String genGUID(){
8 return new BigInteger(165, new Random()).toString(36).toUpperCase();
9 }
10 }
在Demo中调用这个方法,使得名字唯一,一下代码解决了一个文件夹文件过多;限制文件的类型;上传文件大小限制;手动处理文件上传时的临时文件问题:
1 import java.io.File;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.io.UnsupportedEncodingException;
7 import java.text.DateFormat;
8 import java.text.SimpleDateFormat;
9 import java.util.ArrayList;
10 import java.util.Date;
11 import java.util.List;
12
13 import javax.servlet.ServletException;
14 import javax.servlet.http.HttpServlet;
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse;
17
18 import org.apache.commons.fileupload.FileItem;
19 import org.apache.commons.fileupload.FileUploadBase;
20 import org.apache.commons.fileupload.FileUploadException;
21 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
22 import org.apache.commons.fileupload.servlet.ServletFileUpload;
23 import org.apache.commons.io.FilenameUtils;
24
25 import com.itheima.util.IdGenertor;
26
27 public class UploadServlet3 extends HttpServlet {
28
29 public void doGet(HttpServletRequest request, HttpServletResponse response)
30 throws ServletException, IOException {
31 request.setCharacterEncoding("UTF-8");
32 response.setContentType("text/html;charset=UTF-8");
33
34 //检测form是否是multipart/form-data类型的
35 boolean isMultipart = ServletFileUpload.isMultipartContent(request);
36 if(!isMultipart){
37 throw new RuntimeException("The form's enctype attribute value must be multipart/form-data");
38 }
39 //解析请求内容
40 DiskFileItemFactory factory = new DiskFileItemFactory();//产生FileItem的工厂
41 factory.setRepository(new File("d:/"));//指定临时文件的存放目录
42 ServletFileUpload sfu = new ServletFileUpload(factory);
43
44 // sfu.setFileSizeMax(3*1024*1024);//单个文件大小限制
45 // sfu.setSizeMax(5*1024*1024);//总文件大小
46
47 List<FileItem> items = new ArrayList<FileItem>();
48 try {
49 items = sfu.parseRequest(request);
50 }catch(FileUploadBase.FileSizeLimitExceededException e) {
51 response.getWriter().write("单个文件不能超过3M");
52 }
53 catch(FileUploadBase.SizeLimitExceededException e) {
54 response.getWriter().write("总文件不能超过5M");
55 }catch (FileUploadException e) {
56 e.printStackTrace();
57 throw new RuntimeException("解析请求失败");
58 }
59 //遍历:
60 for(FileItem item:items){
61 //处理普通字段
62 if(item.isFormField()){
63 processFormField(item);
64 }else{
65 //处理上传字段
66 processUploadField(item);
67 }
68 }
69 }
70
71 protected void processUploadField(FileItem item) {
72 try {
73
74
75 // InputStream in = item.getInputStream();
76 //找一个存放文件的位置;存放的文件名
77 String fileName = item.getName();//上传的文件的文件名 C:UserswzhtingDesktopa.txt a.txt(浏览器不同)
78 if(fileName!=null&&!fileName.equals("")){
79
80 //限定上传文件的类型
81 if(!item.getContentType().startsWith("image")){
82 return;
83 }
84
85
86 fileName = FilenameUtils.getName(fileName);
87 fileName = IdGenertor.genGUID()+"_"+fileName;
88
89 //存放路径
90 String realPath = getServletContext().getRealPath("/WEB-INF/files");
91
92 //生成一个子目录
93 String childDirectory = genChildDirectory(realPath,fileName);
94
95 File storeDirectory = new File(realPath+File.separator+childDirectory);
96 if(!storeDirectory.exists()){
97 storeDirectory.mkdirs();
98 }
99 // OutputStream out = new FileOutputStream(new File(storeDirectory, fileName));
100 //
101 // int len = -1;
102 // byte b[] = new byte[1024];
103 // while((len=in.read(b))!=-1){
104 // out.write(b, 0, len);
105 // }
106 // in.close();
107 // out.close();
108 //
109 // item.delete();//清除临时文件
110
111 item.write(new File(storeDirectory, fileName));
112 }
113
114
115 } catch (Exception e) {
116 e.printStackTrace();
117 }
118 }
119 private String genChildDirectory(String realPath, String fileName) {
120 int hashCode = fileName.hashCode();
121 int dir1 = hashCode&0xf;
122 int dir2 = (hashCode&0xf0)>>4;
123
124 String str = dir1+File.separator+dir2;
125
126 File file = new File(realPath,str);
127 if(!file.exists()){
128 file.mkdirs();
129 }
130
131 return str;
132
133 }
134
135 //按照日期生成子目录
136 private String genChildDirectory(String realPath) {
137 Date now = new Date();
138 DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
139 String str = df.format(now);
140
141 File file = new File(realPath,str);
142 if(!file.exists()){
143 file.mkdirs();
144 }
145
146 return str;
147 }
148
149 protected void processFormField(FileItem item) {
150 //打印到控制台
151 String fieldName = item.getFieldName();
152 String fieldValue = "";
153 try {
154 fieldValue = item.getString("UTF-8");
155 } catch (UnsupportedEncodingException e) {
156 e.printStackTrace();
157 }
158 System.out.println(fieldName+"="+fieldValue);
159 }
160
161 public void doPost(HttpServletRequest request, HttpServletResponse response)
162 throws ServletException, IOException {
163 doGet(request, response);
164 }
165
166 }
- 文件的下载
1 package com.itheima.servlet; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.net.URLEncoder; 9 10 import javax.servlet.ServletException; 11 import javax.servlet.http.HttpServlet; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 //文件下载 15 public class DownloadServlet extends HttpServlet { 16 17 public void doGet(HttpServletRequest request, HttpServletResponse response) 18 throws ServletException, IOException { 19 //得到文件名 20 String uuidFileName = request.getParameter("filename"); 21 uuidFileName = new String(uuidFileName.getBytes("ISO-8859-1"),"UTF-8"); 22 23 //存在哪里 24 String realPath = getServletContext().getRealPath("/WEB-INF/files"); 25 String childDirectory = genChildDirectory(realPath,uuidFileName); 26 27 String fullPath = realPath+File.separator+childDirectory+File.separator+uuidFileName; 28 29 //告知客户端以下载的方式 30 String oldFilename = uuidFileName.substring(uuidFileName.indexOf("_")+1); 31 response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(oldFilename, "UTF-8")); 32 33 InputStream in = new FileInputStream(fullPath); 34 OutputStream out = response.getOutputStream(); 35 int len = -1; 36 byte b[] = new byte[1024]; 37 while((len=in.read(b))!=-1){ 38 out.write(b, 0, len); 39 } 40 in.close(); 41 42 } 43 44 public void doPost(HttpServletRequest request, HttpServletResponse response) 45 throws ServletException, IOException { 46 doGet(request, response); 47 } 48 private String genChildDirectory(String realPath, String fileName) { 49 int hashCode = fileName.hashCode(); 50 int dir1 = hashCode&0xf; 51 int dir2 = (hashCode&0xf0)>>4; 52 53 String str = dir1+File.separator+dir2; 54 55 File file = new File(realPath,str); 56 if(!file.exists()){ 57 file.mkdirs(); 58 } 59 60 return str; 61 62 } 63 }
Enjoy Reading This Article?
Here are some more articles you might like to read next: