springboot中怎么实现切割分片上传功能
创始人
2024-12-24 09:41:37
0次

文件上传是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=30MBspring.servlet.multipart.max-request-size=35MB

说明:

设置的数值虽好比前端传过来的大,要不容易报错

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...