这篇文章给大家分享的是有关spring boot实现切割分片上传的方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
从事四川联通机房服务器托管,服务器租用,云主机,网站空间,域名注册,CDN,网络代维等服务。
文件上传是web开发中经常会遇到的
springboot的默认配置为10MB,大于10M的是传不上服务器的,需要修改默认配置
但是如果修改支持大文件又会增加服务器的负担。
当文件大于一定程度时,不仅服务器会占用大量内存,而且http传输极可能会中断。
可以采用切割分片上传
html5提供的文件API中可以轻松的对文件进行分割切片,然后通过ajax异步处理向服务器传输数据,突破对大文件上传的限制,
同时异步处理在一定程度上也提高了文件上传的效率。
过程描述:
将文件分割成N片
处理分片,前台会多次调用上传接口,每次都会上传文件的一部分到服务端
N个分片都上传完成后,将N个文件合并为一个文件,并将N个分片文件删除
1.服务端
(1)添加依赖
commons-fileupload commons-fileupload 1.3.3
(2)UploadController
package com.example.demo.controller;
import com.example.demo.core.Result;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
@CrossOrigin
@Controller
@RequestMapping("/api/upload")
public class UploadController {
@PostMapping("/part")
@ResponseBody
public Result bigFile(HttpServletRequest request, HttpServletResponse response, String guid, Integer chunk, MultipartFile file, Integer chunks) {
try {
String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
;
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
if (chunk == null) chunk = 0;
// 临时目录用来存放所有分片文件
String tempFileDir = projectUrl + "/upload/" + guid;
File parentFileDir = new File(tempFileDir);
if (!parentFileDir.exists()) {
parentFileDir.mkdirs();
}
// 分片处理时,前台会多次调用上传接口,每次都会上传文件的一部分到后台
File tempPartFile = new File(parentFileDir, guid + "_" + chunk + ".part");
FileUtils.copyInputStreamToFile(file.getInputStream(), tempPartFile);
}
} catch (Exception e) {
return Result.failMessage(400,e.getMessage());
}
return Result.successMessage(200,"上次成功");
}
@RequestMapping("merge")
@ResponseBody
public Result mergeFile(String guid, String fileName) {
// 得到 destTempFile 就是最终的文件
String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
try {
String sname = fileName.substring(fileName.lastIndexOf("."));
//时间格式化格式
Date currentTime = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
//获取当前时间并作为时间戳
String timeStamp = simpleDateFormat.format(currentTime);
//拼接新的文件名
String newName = timeStamp + sname;
simpleDateFormat = new SimpleDateFormat("yyyyMM");
String path = projectUrl + "/upload/";
String tmp = simpleDateFormat.format(currentTime);
File parentFileDir = new File(path + guid);
if (parentFileDir.isDirectory()) {
File destTempFile = new File(path + tmp, newName);
if (!destTempFile.exists()) {
//先得到文件的上级目录,并创建上级目录,在创建文件
destTempFile.getParentFile().mkdir();
try {
destTempFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
for (int i = 0; i < parentFileDir.listFiles().length; i++) {
File partFile = new File(parentFileDir, guid + "_" + i + ".part");
FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);
//遍历"所有分片文件"到"最终文件"中
FileUtils.copyFile(partFile, destTempfos);
destTempfos.close();
}
// 删除临时目录中的分片文件
FileUtils.deleteDirectory(parentFileDir);
return Result.successMessage(200,"合并成功");
}else{
return Result.failMessage(400,"没找到目录");
}
} catch (Exception e) {
return Result.failMessage(400,e.getMessage());
}
}
}说明:
注解 @CrossOrigin 解决跨域问题
(3)Result
package com.example.demo.core; import com.alibaba.fastjson.JSON; /** * Created by Beibei on 19/02/22 * API响应结果 */ public class Result{ private int code; private String message; private T data; public Result setCode(Integer code) { this.code = code; return this; } public int getCode() { return code; } public String getMessage() { return message; } public Result setMessage(String message) { this.message = message; return this; } public T getData() { return data; } public Result setData(T data) { this.data = data; return this; } @Override public String toString() { return JSON.toJSONString(this); } public static Result fail(Integer code,T data) { Result ret = new Result (); ret.setCode(code); ret.setData(data); return ret; } public static Result failMessage(Integer code,String msg) { Result ret = new Result (); ret.setCode(code); ret.setMessage(msg); return ret; } public static Result successMessage(Integer code,String msg) { Result ret = new Result (); ret.setCode(code); ret.setMessage(msg); return ret; } public static Result success(Integer code,T data) { Result ret = new Result (); ret.setCode(code); ret.setData(data); return ret; } }
2.前端
(1)使用插件
webuploader,下载 https://github.com/fex-team/webuploader/releases
选择文件

(2)不使用插件
直接用HTML5的File API

3.优化
springboot的默认配置为10MB,前端分片改为20M时,就会报错
org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (10486839) exceeds the configured maximum (10485760)
解决方法:
在 src/main/resources 下的 application.properties里添加
spring.servlet.multipart.max-file-size=30MB spring.servlet.multipart.max-request-size=35MB
说明:
设置的数值虽好比前端传过来的大,要不容易报错
感谢各位的阅读!关于“spring boot实现切割分片上传的方法”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!