文件的上传方式
一、Javaweb方式
- 测试:8MB的文件,耗时64
- Servlet+fileupload
导入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
核心代码
/**
* Created by KingsLanding on 2022/10/4 13:24
*/
@Slf4j
@WebServlet(urlPatterns = "/FileServlet")
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 上传配置
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 检测是否为多媒体上传
if (!ServletFileUpload.isMultipartContent(request)) {
// 如果不是则停止
PrintWriter writer = response.getWriter();
writer.println("Error: 表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
// 配置上传参数
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大文件上传值
upload.setFileSizeMax(MAX_FILE_SIZE);
// 设置最大请求值 (包含文件和表单数据)
upload.setSizeMax(MAX_REQUEST_SIZE);
// 中文处理
upload.setHeaderEncoding("UTF-8");
// 这个路径相对当前应用的目录
String uploadPath = request.getServletContext().getRealPath("/upload/") ;
// 如果目录不存在则创建
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
// 解析请求的内容提取文件数据
long start = System.currentTimeMillis();
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
// 迭代表单数据
for (FileItem item : formItems) {
// 处理不在表单中的字段
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 保存文件到硬盘
item.write(storeFile);
long end = System.currentTimeMillis();
log.info("总耗时:"+(end-start));//总耗时:64
}
}
}
} catch (Exception ex) {
}
// 跳转
response.sendRedirect("/index");
}
}
二、Spring
1.基本流
- 测试:8MB的文件,耗时22
/**
* Created by KingsLanding on 2022/10/3 21:55
*/
@Slf4j
@Controller
public class FileUpload {
@GetMapping("/index")
public String testFormLayouts(){
return "file";
}
@PostMapping("/FileUpload")
public String testUpload(@RequestPart("photo") MultipartFile header,//处理单文件上传
HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取当前工程下photo目录的真实路径
String photo = servletContext.getRealPath("/photo/");
File file = new File(photo);
if (!file.exists()){
file.mkdir();
}
//最终路径
String photoPath=photo+header.getOriginalFilename();
//基本流
FileOutputStream fis=null;
try {
fis = new FileOutputStream(new File(photoPath));
long start = System.currentTimeMillis();
if (!header.isEmpty()){
byte[] bytes = header.getBytes();
fis.write(bytes);
}
long end = System.currentTimeMillis();
log.info("总耗时:"+(end-start));//总耗时:11
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis!=null){
fis.close();
}
}
log.info("上传的文件名:"+header.getOriginalFilename()+"存储位置:"+photoPath+"文件大小"+header.getSize());
return "file";
}
}
2.缓冲流
- 测试:8MB的文件,耗时11
/**
* Created by KingsLanding on 2022/10/5 20:07
*/
@Controller
@Slf4j
public class FileUploadBuffer {
@PostMapping("/FileUploadBuffer")
public String testUpload(@RequestPart("photo") MultipartFile header,//处理单文件上传
HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取当前工程下photo目录的真实路径
String photo = servletContext.getRealPath("/photoBuffer/");
File file = new File(photo);
if (!file.exists()){
file.mkdir();
}
String photoPath=photo+header.getOriginalFilename();
//缓冲流处理
FileOutputStream fis=null;
BufferedOutputStream fos=null;
try {
fis = new FileOutputStream(new File(photoPath));
fos = new BufferedOutputStream(fis);
long startBf = System.currentTimeMillis();
if (!header.isEmpty()){
byte[] bytes = header.getBytes();
fos.write(bytes);
}
long endBf = System.currentTimeMillis();
log.info("总耗时"+(endBf-startBf));//总耗时11
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos!=null){
fos.close();
}
}
log.info("上传的文件名:"+header.getOriginalFilename()+"存储位置:"+photoPath+"文件大小"+header.getSize());
return "file";
}
}
3.getInputStream()
- 测试:8MB的文件,耗时3873
/**
* Created by KingsLanding on 2022/10/5 20:07
*/
@Controller
@Slf4j
public class FileUploadGetInputStream {
@PostMapping("/FileUploadGetInputStream")
public String testUpload(@RequestPart("photo") MultipartFile header,//处理单文件上传
HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取当前工程下photo目录的真实路径
String photo = servletContext.getRealPath("/photoStream/");
File file = new File(photo);
if (!file.exists()){
file.mkdir();
}
String photoPath=photo+header.getOriginalFilename();
//getInputStream();
FileOutputStream fis01=null;
try {
long start = System.currentTimeMillis();
if (!header.isEmpty()){
InputStream inputStream = header.getInputStream();
File file01 = new File(photoPath);
fis01 = new FileOutputStream(file01);
byte[] bytes = new byte[10];
int len;
while ((len=inputStream.read(bytes)) != -1){
fis01.write(bytes,0,len);
}
}
long end = System.currentTimeMillis();
log.info("总耗时:"+(end-start));//总耗时:3873
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis01!=null){
fis01.close();
}
}
log.info("上传的文件名:"+header.getOriginalFilename()+"存储位置:"+photoPath+"文件大小"+header.getSize());
return "file";
}
}
4.transferTo
- 测试:8MB的文件,耗时5
/**
* Created by KingsLanding on 2022/10/5 20:08
*/
@Slf4j
@Controller
public class FileUploadTransferTo {
@PostMapping("/FileUploadTransferTo")
public String testUpload(@RequestPart("photo") MultipartFile header,//处理单文件上传
HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取当前工程下photo目录的真实路径
String photo = servletContext.getRealPath("/photoTransferTo/");
File file = new File(photo);
if (!file.exists()){
file.mkdir();
}
String photoPath=photo+header.getOriginalFilename();
//transferTo
if (!(header.isEmpty())){
long start = System.currentTimeMillis();
header.transferTo(new File(photoPath));
long end = System.currentTimeMillis();
log.info("耗时:"+(end-start));//耗时:5
}
log.info("上传的文件名:"+header.getOriginalFilename()+"存储位置:"+photoPath+"文件大小"+header.getSize());
return "file";
}
}
前端测试界面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
基本流的文件上传:
<form th:action="@{/FileUpload}" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="photo"/>
<input type="submit" value="上传"/>
</form>
<br>
缓冲流的文件上传:
<form th:action="@{/FileUploadBuffer}" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="photo"/>
<input type="submit" value="上传">
</form>
<br>
getInputStream文件上传:
<form th:action="@{/FileUploadGetInputStream}" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="photo"/>
<input type="submit" value="上传">
</form>
<br>
transferTo文件上传:
<form th:action="@{/FileUploadTransferTo}" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="photo"/>
<input type="submit" value="上传">
</form>
<br>
Servlet文件上传:
<form th:action="@{/FileServlet}" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="photo"/>
<input type="submit" value="上传">
</form>
</body>
</html>