先说一下传统文件上传的原理,上传文件是将form表单的类型改为上传文件的类型,而且只能使用post格式,因为get太短,不足以放下文件。在请求正文中,会以分割的形式来传送文件,服务器端在接受到文件请求后,通过解析request来拿到文件,具体使用的类和用法见下:
form表单:
<%--
Created by IntelliJ IDEA.
User: Sun Jingjun
Date: 2020/2/24
Time: 11:23
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="/mvc/fileupload" enctype="multipart/form-data" method="post">
选择文件:<input type="file" name="file"><br/>
<input type="submit" value="上传">
</form>
</body>
</html>
首先,引入处理解析request中文件的jar包
<!--文件上传-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<!--Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
引入依赖后,写一个Servlet,可以去实现接口,这里直接继承HttpServlet
public class FileUploadController extends 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 {
}
}
然后附上类的使用及注释:
@WebServlet("/fileupload")
public class FileUploadController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("...");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
File file = new File(path);
if(!file.exists()) {
file.mkdirs();
}
//解析request对象,获取上传文件
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = null;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
//遍历
for (FileItem item : items) {
//判断该项是否为文件
if(item.isFormField()) {
//是普通表单
} else {
String fileName = item.getName();
String uuid = UUID.randomUUID().toString().replace("-", "");
fileName = uuid + "_" + fileName;
//完成文件上传
try {
item.write(new File(path,fileName));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("wirte finish");
//删除临时文件,如果大于10k,会产生临时文件,小于则在内存
item.delete();
}
}
}
}
到这里,就介绍完了。最后说一个问题,就是当以war形式进行部署时,项目会部署到Tomcat的webapps底下,每次重启Tomcat时都会删除掉上次的文件。而如果以war explode形式启动,则会直接将idea workplace底下的文件夹直接放在服务端,所以这两种形式启动,getRealPath的路径是不一样的