1.对应的java代码
package fileUpLoad;
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;
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;
public class FileUpload extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断上传的文件是普通表单还是带文件表单
String msg = "上传失败";
if(!ServletFileUpload.isMultipartContent(req)){
req.setAttribute("msg",msg);
req.getRequestDispatcher("error.jsp").forward(req,resp);
return;//如果是普通表单,则终止方法
}
try {
//获取上传路径,上传路径建议放到WEB-INF里面用户无法直接访问,安全
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()){
uploadFile.mkdir();//该目录不存在,创建该路径
}
//缓存,零时文件
//如果缓存文件超过了预定大小,我们需要把文件放到一个零时文件中,过几天自动删除,或者提醒用户将文件转存为永久。
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tempFile = new File(tempPath);
if (!tempFile.exists()){
tempFile.mkdir();//该目录不存在,创建该路径
}
//处理上传文件需要使用req.getInputStream(),原生方法,使用比较麻烦
//建议使用Apache的文件上传组件common-fileupload,它依赖于common-io组件
//处理上传文件
//1,创建磁盘工厂对象DiskFileItemFactory,处理上传的路径或者大小限制
DiskFileItemFactory factory = getDiskFileItemFactory(tempFile);
//2.通过磁盘工厂对象获取文件上传对象ServletFileUpload
//ServletFileUpload对象负责将每个表单选项封装成一个个FileItem对象
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件
msg = uploadParseRequest(upload,req,uploadPath);
//4.返回上传结果
req.setAttribute("msg",msg);
req.getRequestDispatcher("info.jsp").forward(req,resp);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
}
//创建磁盘工厂对象
public static DiskFileItemFactory getDiskFileItemFactory(File file){
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂创建缓冲区,当上传文件大于这个缓冲区的时候,他将放到这个零时文件中
factory.setSizeThreshold(1024*1024);//设置缓存区大小为1M
factory.setRepository(file);//零时文件目录
return factory;
}
//创建ServletUpload对象
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
ServletFileUpload upload = new ServletFileUpload(factory);
//监听上传进度
upload.setProgressListener(new ProgressListener() {
/*
* 参数一:已上传大小
* 参数二:总大小
* */
public void update(long l, long l1, int i) {
System.out.println("文件已上传:"+(double)(l*100/l1)+"%");
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件最大值10M
upload.setFileSizeMax(10*1024*1024);
//设置总共能上传的大小10M
upload.setSizeMax(1024*1024*10);
return upload;
}
//处理上传文件
public static String uploadParseRequest(ServletFileUpload upload ,HttpServletRequest request, String uploadPath) throws FileUploadException,IOException {
String msg = "";
//把前端请求解析,封装成FileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
//fileItems 表单选项对象
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);
//如果后缀名不对,不是我们想要的类型,直接return,不处理告诉用户不是我们想要的
/*
* 网络传输的东西都需要序列化
* pojo,实体类,如果想要在多台电脑上运行,都需要序列化
* interface Serializable :标记接口,标记意义:序列化
* JVM-->调用本地方法栈(native,是使用C++编写的方法),native-->C++
* */
//使用UUID类,生成一个唯一的识别标码,作为上传的文件名
String uuidPath = UUID.randomUUID().toString();
//=========文件处理完毕====
//保存文件
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[] buffer = new byte[1024*1024];
int len = 0;
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
out.close();
in.close();
msg = "文件上传完成";
fileItem.delete();
//=======文件传输完成
}
}
return msg;
}
}
2.对应的JSP代码
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>fileUpLoad</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
<p>
上传用户:<input type="text" name="userName">
</p>
<p>
<input type="file" name=file1">
</p>
<p>
<input type="file" name="file2">
</p>
<input type="submit">|<input type="reset">
</form>
</body>
</html>
3.对应的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>FileUpLoad</servlet-name>
<servlet-class>fileUpLoad.FileUpLoad</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileUpLoad</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
4.项目对应的maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>fileUpLode</artifactId>
<version>1.0-SNAPSHOT</version>
<name>fileUpLode</name>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
5.使用注意事项
注意:
文件上传需要使用post提交
post 文件上传大小没限制
get 文件上传有限制
如果表单添加控件属性为enctype = multipart/form-data
服务器端想获取文件就需要使用流获取
文件上传必须要在form表单添加enctype控件
处理上传文件需要使用req.getInputStream()
,原生方法,使用比较麻烦
建议使用Apache的文件上传组件common-fileupload,它依赖于common-io组件所以需要导入common-fileupload和common-io两个jar包