Java学习——文件上传
1.准备
导入jar包:
准备工作当然首要的是导入jar包。文件上传一般使用的是apache的开源工具common-fileupload组件。但是这个组件是依赖于common-io这个包的,所以我们要下载并导入这两个jar包。
jar包下载地址:
https://mvnrepository.com/artifact/commons-io/commons-io
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
然后我们创建的是一个Web项目当然要导入servlet的一系列jar包了,以下就是所有的jar包
几个使用到的类介绍:
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象, 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
FileItem类:在HTML页面input 必须有 name <input type="file" name="filename">
ServletFileUpload 类:ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中 . 使用其parseRequest(HttpServletRequest) 方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。
注意事项:
- 一般我们将上传到服务器的文件放在WEB-INF目录下
- 为了防止上传的文件因为重名被覆盖,我们会使用UUID生成随机字符串给每一个文件夹取不一样的文件名
- 要限制上传的文件最大值
- 可以限制文件上传的类型,通过后缀名判断是否合法
2.编写代码
编写前端JSP页面
1.首页index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<b><a href="upload.jsp">点击进去上传文件</a></b>
</body>
</html>
2.上传文件页面upload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
注意:method必须为post,因为get无法获取较大数据的文件,post对上传的数据大小没有限制
enctype一定要设置成multipart/form-data类型,表示表单中存在上传数据
--%>
<form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
<p>用户:<input type="text" name="username"></p>
<p>文件:<input type="file" name="uploadFile"></p>
<p><input type="submit" value="提交"></p>
</form>
</body>
</html>
3.上传成功提示页info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
${msg}==${pageContext.request.contextPath}/upload.do
--%>
${msg}/upload.do
</body>
</html>
编写Servlet,在Servlet中实现上传的逻辑
package com.muhan.servlet;
import org.apache.commons.fileupload.FileItem;
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.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 UploadServlet extends javax.servlet.http.HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断上传的文件是普通表单还是带文件的表单,如果是普通表单就直接返回
if (!ServletFileUpload.isMultipartContent(req)){
return;
}
//如果是带文件的表单
//1.创建上传文件的保存路径,建议在WEB-INF下,安全,用户无法直接访问
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()){
uploadFile.mkdir();
}
//2.创建临时文件,假如文件超过了预期的大小,我们就把它放在一个临时恩建,过几天自动删除
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File file = new File(tmpPath);
if (!file.exists()){
file.mkdir();
}
//3.处理上传的文件,一般通过流使用。
// 可以使用apache的文件上传组件common-fileupload,它要依赖commons-io
//3.1创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
DiskFileItemFactory factory = getDiskFileItemFactory(file);
//3.2获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.3把前端请求解析,封装成一个FileItem对象,处理上传文件
String msg="";
try {
msg = parseUploadResquest(req, uploadPath, upload);
} catch (FileUploadException e) {
e.printStackTrace();
}
//4.Servlet请求转发消息
req.setAttribute("msg",msg);
req.getRequestDispatcher("info.jsp").forward(req,resp);
}
/**
* 3.1创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
*/
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过工厂设置一个缓冲区,当上传的文件大于这个缓冲区时,把它放到临时文件中
factory.setSizeThreshold(1024*1024);//设置缓冲区大小为1M
factory.setRepository(file);//临时文件的保存目录
return factory;
}
/**
* 3.2获取ServletFileUpload
*/
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener() {
@Override
public void update(long pBytesRead, long pContentLength, int pItem) {
//pBytesRead:读取到的文件大小
//pContentLength:文件大小
System.out.println("总大小"+pBytesRead+"已经上传:"+pBytesRead);
}
});
//处理乱码问题
upload.setHeaderEncoding("utf-8");
//设置单个文件的最大值为10M
upload.setFileSizeMax(1024*1024*10);
//设置总共能够上传文件的大小为100M
upload.setSizeMax(1024*1024*100);
return upload;
}
/**
* 3.3处理上传文件
*/
private String parseUploadResquest(HttpServletRequest req, String uploadPath, ServletFileUpload upload) throws FileUploadException, IOException {
List<FileItem> fileItems = upload.parseRequest(req);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()==true){//判断上传的是普通表单还是带文件的表单
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){
return "文件名不存在,无法保存(未知文件)";
}
//获得上传的文件名
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
String fileEndName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
System.out.println("文件信息,文件名:"+fileName+"文件类型:"+fileEndName);
//使用UUID(位移识别的通用吗)保证文件名不重名
String uuidPath = UUID.randomUUID().toString();//uuid码
//=============================处理文件完毕===========================
//文件存到哪儿?文件真实存在路径realPath
String realPath = uploadPath + "/" + uuidPath;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realPath);
if (!realPathFile.exists()){
realPathFile.mkdir();
}
//============================存放文件完毕===========================
//获取文件上传的流
InputStream in = fileItem.getInputStream();
//创建一个文件输出流
FileOutputStream out = new FileOutputStream(realPath+"/"+fileName);
byte[] bytes = new byte[1024 * 8];//创建一个缓冲区
int len = 0;
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
in.close();
out.close();
//=======================文件传输完毕================================
fileItem.delete();//上传成功之后删除临时文件
}
}
return "文件上传成功";
}
}
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.muhan.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
</web-app>
3.配置Tomcat测试
查看上传的文件: