Java学习笔记(五):文件的上传和下载

  • 文件上传原理

1、文件上传的前提: a、表单的method必须是post b、表单的enctype属性必须是multipart/form-data c、表单中提供input type=”file” <p align="center"> screenshot </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)

screenshot

  • 利用第三方组件实现文件上传

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"> screenshot </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:

  • What is Mathematics: Solution Chapter 3
  • What is Mathematics: Solution Chapter 2
  • What is Mathematics: Solution Chapter 1
  • A small guide to supplements: What you need to know
  • 混乱与秩序