這篇文章給大家分享的是有關(guān)spring boot實現(xiàn)切割分片上傳的方法的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
從事四川聯(lián)通機房服務(wù)器托管,服務(wù)器租用,云主機,網(wǎng)站空間,域名注冊,CDN,網(wǎng)絡(luò)代維等服務(wù)。
文件上傳是web開發(fā)中經(jīng)常會遇到的
springboot的默認(rèn)配置為10MB,大于10M的是傳不上服務(wù)器的,需要修改默認(rèn)配置
但是如果修改支持大文件又會增加服務(wù)器的負(fù)擔(dān)。
當(dāng)文件大于一定程度時,不僅服務(wù)器會占用大量內(nèi)存,而且http傳輸極可能會中斷。
可以采用切割分片上傳
html5提供的文件API中可以輕松的對文件進(jìn)行分割切片,然后通過ajax異步處理向服務(wù)器傳輸數(shù)據(jù),突破對大文件上傳的限制,
同時異步處理在一定程度上也提高了文件上傳的效率。
過程描述:
將文件分割成N片
處理分片,前臺會多次調(diào)用上傳接口,每次都會上傳文件的一部分到服務(wù)端
N個分片都上傳完成后,將N個文件合并為一個文件,并將N個分片文件刪除
1.服務(wù)端
(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(); } // 分片處理時,前臺會多次調(diào)用上傳接口,每次都會上傳文件的一部分到后臺 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"); //獲取當(dāng)前時間并作為時間戳 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()) { //先得到文件的上級目錄,并創(chuàng)建上級目錄,在創(chuàng)建文件 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響應(yīng)結(jié)果 */ 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.優(yōu)化
springboot的默認(rèn)配置為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
說明:
設(shè)置的數(shù)值雖好比前端傳過來的大,要不容易報錯
感謝各位的閱讀!關(guān)于“spring boot實現(xiàn)切割分片上傳的方法”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!