Servlet 文件上传与下载

本文最后更新于:2024年3月18日 凌晨

Servlet 文件上传与下载

pom.xml

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>

文件上传

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
@WebServlet(urlPatterns ={"/Examples/Servlet.UploadFiles/FileServlet"})
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 判断上传的文件是普通表单还是带文件的表单。
if (!ServletFileUpload.isMultipartContent(request)) {
return;// 终止方法运行,说明这是一个普通的表单,直接返回。
}
// 创建上传文件的保存路径,建议保存在WEB-INF路径下,安全,用户无法直接访问上传的文件。
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdir();// 创建这个目录。
}
// 缓存,临时文件。
// 临时路径,假如文件超过了预期的大小,放到一个临时文件夹中,过几天自动删除,或者提醒用户转存为永久。
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File file = new File(tmpPath);
if (!file.exists()) {
file.mkdir();// 创建这个目录。
}
// 处理上传的文件,一般都需要通过流来获取,可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦。
// 建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件。

/*
*ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象
* 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
* 所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象。
* 通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory
*/
try {
//1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制。
DiskFileItemFactory factory = getDiskFileItemFactory(file);
//2.获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件。

String msg = uploadParseRequest(upload, request, uploadPath);
//servlet请求转发消息。
request.setAttribute("msg", msg);
request.getRequestDispatcher("info.jsp").forward(request, response);
} catch (FileUploadException e) {
e.printStackTrace();
}
}


public static DiskFileItemFactory getDiskFileItemFactory(File file) {
// 创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的:
DiskFileItemFactory factory = new DiskFileItemFactory();
// 通过这个工厂设置一个缓冲区,当上传文件大于这个缓冲区的时候,将他放到临时文件中。
factory.setSizeThreshold(1024 * 1024);// 缓冲区大小为1M
factory.setRepository(file);// 临时目录的保存目录,需要一个tmpFile
return factory;
}

public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
// 获取ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(factory);
// 监听文件上传进度。
upload.setProgressListener(new ProgressListener() {
@Override
//pBytesRead:已经读取到的文件大小。
//pContentLength:文件大小。
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
}
});
// 处理乱码问题。
upload.setHeaderEncoding("UTF-8");
// 设置单个文件的最大值。
upload.setFileSizeMax(1024 * 1024 * 10);
// 设置总共能够上传文件的大小。
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}

public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) throws FileUploadException, IOException {
String msg = "";
// 处理上传文件。
// 把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象。
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
// 判断上传的文件是普通的表单还是带文件的表单。
if (fileItem.isFormField()) {
//getFieldName指的是前端表单控件的name
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");// 处理乱码。
System.out.println(name + ":" + value);
} else {// 文件。
// 处理文件。
// 拿到文件名字。
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名:"+uploadFileName);

// 可能存在文件名不合法的情况。
if (uploadFileName.trim().equals("") || uploadFileName == null) {
continue;
}
// 获得上传文件的文件名。
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
// 获得文件的后缀名。
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
System.out.println("文件名:"+fileName+"后缀名"+fileExtName);
/*
如果文件后缀名fileExtName不是所需要的,就直接return,不处理,告诉用户文件类型不对。
*/
// 可以使用UUID(唯一识别的通用码),保证文件名唯一。
String uuidPath = UUID.randomUUID().toString();
// 文件真实存在的地址realPath
String realPath = uploadPath + "/" + uuidPath;
// 给每个文件创建一个对应的文件夹。
File realPathFile = new File(realPath);
if (!realPathFile.exists()) {
realPathFile.mkdir();
}
// 文件传输。
// 获取文件上传的流。
InputStream inputStream = fileItem.getInputStream();
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);

// 创建一个缓冲区。
byte[] buffer = new byte[1024 * 1024];

// 判断是否读取完毕。
int len = 0;
// 如果大于0说明还存在数据。
while ((len = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
// 关闭流。
fos.close();
inputStream.close();

msg = "文件上传成功!";
fileItem.delete();// 上传成功,清除临时文件。
}
}
return msg;
}
}

文件下载

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
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
// 要下载的图片地址。
String path = request.getServletContext().getRealPath("/upload");
String fileName = "基础语法.jpg";

//1,设置response 响应头。
response.reset(); // 设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); // 字符编码。
response.setContentType("multipart/form-data"); // 二进制传输数据。
// 设置响应头。
response.setHeader("Content-Disposition","attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));

File file = new File(path,fileName);
//2,读取文件--输入流。
FileInputStream input=new FileInputStream(file);
//3,写出文件--输出流。
ServletOutputStream out = response.getOutputStream();

byte[] buff =new byte[1024];
int index=0;
//4,执行写出操作。
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}