(1)导包
如果直接使用servlet获取上传文件的输入流,然后再解析里面的请求参数时比较麻烦的,所以一般选择采用apache的开源工具common-fileupload实现文件上传。
由于common-fileupload是依赖于common-io的,所以还需要导入common-io这个包
1.以maven形式
commons-fileupload
commons-fileupload
1.3.1
2.直接导包
(2)实现
1.上传页面编写
只需要将input标签的type定义为file即可
2.响应页面编写
为了能够显示出上传的结果
<%@ page language="java" pageEncoding="UTF-8"%>
消息提示
${message}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 消息提示
String message = "";
boolean success = makeUploadDir();
if (success) {
// 1、判断提交上来的数据是否是上传表单的数据
if (ServletFileUpload.isMultipartContent(request)) {
ServletFileUpload upload = initUploadUitl();
try {
// 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项
List list = upload.parseRequest(request);
for (FileItem item : list) {
if (item.isFormField()) {// 如果fileitem中封装的是普通输入项的数据,直接输出
outputNormalData(item);
} else {// 如果fileitem中封装的是上传文件
String fileNameame = getFileName(item);
if (fileNameame==null) {
message = "文件名为空";
}else {
saveUploadFile(item,fileNameame);
// 删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功!";
}
}
}
}catch (Exception e) {
message = "文件上传失败!";
e.printStackTrace();
}
} else {
message = "表单数据不是上传文件的数据";
}
} else {
message = "创建文件上传目录失败";
}
request.setAttribute("message", message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
3.1创建上传文件的保存目录
private String savePath;
private boolean makeUploadDir() {
// 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
File file = new File(savePath);
// 判断上传文件的保存目录是否存在
if (!file.exists() && !file.isDirectory()) {
System.out.println(savePath + "目录不存在,需要创建");
// 创建目录
return file.mkdir();
} else {
return true;
}
}
private ServletFileUpload initUploadUitl() {
// 使用Apache文件上传组件处理文件上传步骤:
// 1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
return upload;
}
private void outputNormalData(FileItem item) throws UnsupportedEncodingException {
String name = item.getFieldName();
// 解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
System.out.println(name + "=" + value);
}
3.4 获取文件名称
// 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:
// c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
private String getFileName(FileItem item) {
String filename = item.getName();// 得到上传的文件名称
System.out.println(filename);
if (filename == null || filename.trim().equals("")) {
return null;
}else {
// 处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename.substring(filename.lastIndexOf("\\") + 1);
return filename;
}
}
private void saveUploadFile(FileItem item,String fileName) throws IOException {
// 获取item中的上传文件的输入流
InputStream in = item.getInputStream();
// 创建一个文件输出流
FileOutputStream out = new FileOutputStream(
savePath + "\\" + fileName);
// 创建一个缓冲区
byte buffer[] = new byte[1024];
// 判断输入流中的数据是否已经读完的标识
int len = 0;
// 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while ((len = in.read(buffer)) > 0) {
// 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath
// + "\\" + filename)当中
out.write(buffer, 0, len);
}
// 关闭输入流
in.close();
// 关闭输出流
out.close();
}
(3)优化
1.限制上传文件的大小
需要限制单个文件的大小, 并且还可以限制文件上传总量的最大值单个文件大小限制:
upload.setFileSizeMax
文件总量大小限制
upload.setSizeMax
2.监听文件上传进度
传递一个ProgressListener即可upload.setProgressListener(new ProgressListener(){..})
3.设置缓冲区
如果文件大小超过缓冲区大小,就只能写在一个临时文件中factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
//设置上传时生成的临时文件的保存目录
factory.setRepository(tmpFile);
private ServletFileUpload initUploadUitl() {
// 使用Apache文件上传组件处理文件上传步骤:
// 1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
//设置上传时生成的临时文件的保存目录
//上传时生成的临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
// 创建临时目录
tmpFile.mkdir();
}
factory.setRepository(tmpFile);
// 2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
/**
* 文件大小为:14608,当前已处理:4096
文件大小为:14608,当前已处理:7367
文件大小为:14608,当前已处理:11419
文件大小为:14608,当前已处理:14608
*/
}
});
// 解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(1024*1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024*1024*10);
return upload;
}