文件上传
1. 文件上传注意事项
1、为保证服务器的安全,上传的文件应放在外界无法访问的目录下,如WEN-INF。
2、为防止同名文件产生覆盖现象,要为上传的文件产生一个唯一的文件名。
3、要限制上传文件的最大值。
4、限制上传文件的类型,收到文件时,判断文件后缀名是否合法。
2. 新建一个项目
-
新建一个空的java项目
-
在弹出的框里选择项目,然后选择jdk的版本和项目语言的版本。
-
在文件处新建模块
-
把web.xml的版本头更新
<?xml version="1.0" encoding="UTF-8"?>
3. 用到的工具jar包
commons-io-2.6.jar
commons-fileupload-1.4.jar
maven pom.xml配置
commons-io
commons-io
2.6
commons-fileupload
commons-fileupload
1.4
4. 常用方法
//isFormFile方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果时普通表单字段则返回true,否则返回false
boolean isField();
//getFieldName方法用于返回表单标签name属性的值
String getFieldName();
//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();
//getName方法用于获得文件上传字段中的文件名。
String getName();
//以流的形式返回上传文件的数据内容。
InputStream getInputStream();
//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件
void delete();
5. 文件上传Servlet
- 判断是否为上传文件的表单
- 创建文件保存地址和临时文件保存地址
- 创建DiskFileItemFactory对象,设置缓冲区大小,设置临时目录
- 创建ServletFileUpload对象(需传入DiskFileItemFactory对象)
- 通过ServletFileUpload对象设置文件上传进度监听
- 通过ServletFileUpload对象设置头文件编码格式避免乱码,设置单个文件大小,设置总文件大小
- 通过ServletFileUpload对象解析请求获取List
列表 - 遍历List
列表,用isFormField()方法判断每个FileItem对象是否为文件控件(是文件控件结果为false) - 使用UUID解决文件名重复导致覆盖的问题
- 获取文件控件的输入流,传入文件保存地址,实现文件的上传
- 关闭流,清空临时文件
- 转发到前端页面
package com.feng.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//===========================1. 首先判断表单是否为上传文件的表单;==========================
if (!ServletFileUpload.isMultipartContent(req)) {
//普通表单=>终止方法;
return;
}
String message = null;//传递给前端的信息
try {
//带文件的表单;
//==========================2.1 创建上传文件的最终保存地址================================;
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
//拿到上传文件时;若保存地址不存在就去创建保存目录;
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
//创建目录;
uploadFile.mkdir();
}
//===========================2.2使用缓存; 当文件过大时;先存为临时文件;========================
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
//拿到上传文件时;若保存地址不存在就去创建保存目录;
File tempFile = new File(tempPath);
if (!tempFile.exists()) {
//创建临时目录;
tempFile.mkdir();
}
//==============================3. 创建DiskFileItemFactory对象;=============================
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//设置缓冲区大小为 1M;大于这个缓冲区大小的文件,先存在临时文件目录里
diskFileItemFactory.setSizeThreshold(1024 * 1024);
//临时文件保存目录;
diskFileItemFactory.setRepository(tempFile);
//===============================4. 获取ServletFileUpload对象==================================
//作用是处理上传文件数据,将表单的每一项输入封装为Fileltem对象;
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
//====================================5. 监听文件上传进度=======================================;
servletFileUpload.setProgressListener(new ProgressListener() {
//l:已上传的文件字节数; l1:要上传的文件的总字节数; i:上传第几个文件
public void update(long l, long l1, int i) {
System.out.println("已经上传==>" + l + " -文件总大小==>" + l1 + "- 第"+i+"个文件");
}
});
//=====================6. 通过ServletFileUpload对象设置头文件编码格式避免乱码,设置单个文件大小,设置总文件大小==================
// 处理文件乱码;
servletFileUpload.setHeaderEncoding("utf-8");
//设置单个文件最大值; 3M
servletFileUpload.setFileSizeMax(31 * 1024 * 1024);
//设置总大小; 100M
servletFileUpload.setSizeMax(100 * 1024 * 1024);
//=======================7. 前端请求解析; 封装为fileItem对象的列表=================
List fileItems = servletFileUpload.parseRequest(req);
//======================8. 处理上传的文件================================
for (FileItem fileItem : fileItems) {
//判断是输入框还是上传文件的;
//注意这个方法: 当返回 false 时才是文件类型的;
if (fileItem.isFormField()) {
//获取其他标签框的name;
String name = fileItem.getName();
//处理乱码问题;(统一编码)
String value = fileItem.getString("utf-8");
System.out.println(name + "<--->" + value);
} else {
//获取文件名;
String uploadName = fileItem.getName();
System.out.println("上传的文件名==>" + uploadName);
//对空文件名进行限制拦截;
if (uploadName == null || uploadName.trim().equals("")) {
continue;
}
//输入文件的名字;与后缀名;
String realName = uploadName.substring(uploadName.lastIndexOf("/") + 1);
String nameSuffix = uploadName.substring(uploadName.lastIndexOf(".") + 1);
System.out.println("文件名==>" + realName + "后缀文件类型=>" + nameSuffix);
//使用UUID生成的随机通用码保证文件唯一性;
String uploadFileID = UUID.randomUUID().toString();
//=================9. 使用UUID解决文件名重复导致覆盖的问题============
//文件真实地址加上uuid的通用码;
String realPath = uploadPath + "/" + uploadFileID;
File realFile = new File(realPath);
if (!realFile.exists()) {
//创建目录;
realFile.mkdir();
}
//===============================10. 获取文件控件的输入流,传入文件保存地址,实现文件的上传=========================;
InputStream inputStream = fileItem.getInputStream();
//输出流;
FileOutputStream out = new FileOutputStream(realPath + "/" + realName);
//创建传输的缓冲区;
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) > 0) {
out.write(bytes, 0, len);
}
//============11. 关闭流,清空临时文件==========
//关闭;释放资源;
out.close();
inputStream.close();
message = "<==上传成功==>";
//清除临时文件;
fileItem.delete();
}
}
} catch (FileUploadException e) {
message = "失败!!!";
e.printStackTrace();
}
//========================12. 转发到前端页面=============
//转发消息;
req.setAttribute("message", message);
req.getRequestDispatcher("info.jsp").forward(req, resp);
}
}
以上内容参考自:狂神说java