文件上传是web开发中经常会遇到的
springboot的默认配置为10MB,大于10M的是传不上服务器的,需要修改默认配置
但是如果修改支持大文件又会增加服务器的负担。
当文件大于一定程度时,不仅服务器会占用大量内存,而且http传输极可能会中断。
可以采用切割分片上传
html5提供的文件API中可以轻松的对文件进行分割切片,然后通过ajax异步处理向服务器传输数据,突破对大文件上传的限制,同时异步处理在一定程度上也提高了文件上传的效率。
过程描述:
  将文件分割成N片
  处理分片,前台会多次调用上传接口,每次都会上传文件的一部分到服务端
  N个分片都上传完成后,将N个文件合并为一个文件,并将N个分片文件删除
1.服务端
(1)添加依赖
<dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
</dependency>

(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());
        }

    }

}
View Code

说明:

  注解 @CrossOrigin 解决跨域问题

(3)Result

package com.example.demo.core;

import com.alibaba.fastjson.JSON;

/**
 * Created by Beibei on 19/02/22
 * API响应结果
 */
public class Result<T> {
    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 <T>  Result<T> fail(Integer code,T data) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setData(data);
        return ret;
    }

    public static <T>  Result<T> failMessage(Integer code,String msg) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setMessage(msg);
        return ret;
    }
    public static <T>  Result<T> successMessage(Integer code,String msg) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setMessage(msg);
        return ret;
    }

    public static <T> Result<T> success(Integer code,T data) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setData(data);
        return ret;
    }

}
View Code

相关文章:

  • 2022-12-23
  • 2022-01-06
  • 2021-11-20
  • 2021-10-22
  • 2021-06-09
  • 2022-12-23
  • 2021-06-26
  • 2022-12-23
猜你喜欢
  • 2021-12-19
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-12
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案