本篇文章為大家展示了springboot中怎么實現(xiàn)切割分片上傳功能,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
在北川羌族等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網(wǎng)站制作、成都網(wǎng)站建設、外貿(mào)營銷網(wǎng)站建設 網(wǎng)站設計制作按需網(wǎng)站策劃,公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,品牌網(wǎng)站建設,營銷型網(wǎng)站,成都外貿(mào)網(wǎng)站建設公司,北川羌族網(wǎng)站建設費用合理。
文件上傳是web開發(fā)中經(jīng)常會遇到的
springboot的默認配置為10MB,大于10M的是傳不上服務器的,需要修改默認配置
但是如果修改支持大文件又會增加服務器的負擔。
當文件大于一定程度時,不僅服務器會占用大量內(nèi)存,而且http傳輸極可能會中斷。
可以采用切割分片上傳
html5提供的文件API中可以輕松的對文件進行分割切片,然后通過ajax異步處理向服務器傳輸數(shù)據(jù),突破對大文件上傳的限制,
同時異步處理在一定程度上也提高了文件上傳的效率。
過程描述:
將文件分割成N片 處理分片,前臺會多次調(diào)用上傳接口,每次都會上傳文件的一部分到服務端 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(); } // 分片處理時,前臺會多次調(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"); //獲取當前時間并作為時間戳 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響應結(jié)果 */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; }}
2.前端
(1)使用插件
webuploader,下載https://github.com/fex-team/webuploader/releases
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link href="css/webuploader.css" rel="external nofollow" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="jquery-1.10.1.min.js"></script> <script type="text/javascript" src="dist/webuploader.min.js"></script></head><body> <p id="uploader"> <p class="btns"> <p id="picker">選擇文件</p> <button id="startBtn" class="btn btn-default">開始上傳</button> </p> </p></body><script type="text/javascript">var GUID = WebUploader.Base.guid();//一個GUIDvar uploader = WebUploader.create({ // swf文件路徑 swf: 'dist/Uploader.swf', // 文件接收服務端。 server: 'http://localhost:8080/api/upload/part', formData:{ guid : GUID }, pick: '#picker', chunked : true, // 分片處理 chunkSize : 1 * 1024 * 1024, // 每片1M, chunkRetry : false,// 如果失敗,則不重試 threads : 1,// 上傳并發(fā)數(shù)。允許同時最大上傳進程數(shù)。 resize: false});$("#startBtn").click(function () { uploader.upload();});//當文件上傳成功時觸發(fā)。uploader.on( "uploadSuccess", function( file ) { $.post('http://localhost:8080/api/upload/merge', { guid: GUID, fileName: file.name}, function (data) { if(data.code == 200){ alert('上傳成功!'); } });});</script></html>
(2)不使用插件
直接用HTML5的File API
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="jquery-1.10.1.min.js" type="text/javascript"> </script> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> </head> <body> <p id="uploader"> <p class="btns"> <input id="file" name="file" type="file"/> <br> <br> <button id="startBtn"> 開始上傳 </button> </br> </br> </p> <p id="output"> </p> </p> </body> <script type="text/javascript"> var status = 0; var page = { init: function(){ $("#startBtn").click($.proxy(this.upload, this)); }, upload: function(){ status = 0; var GUID = this.guid(); var file = $("#file")[0].files[0], //文件對象 name = file.name, //文件名 size = file.size; //總大小 var shardSize = 20 * 1024 * 1024, //以1MB為一個分片 shardCount = Math.ceil(size / shardSize); //總片數(shù) for(var i = 0;i < shardCount;++i){ //計算每一片的起始與結(jié)束位置 var start = i * shardSize, end = Math.min(size, start + shardSize); var partFile = file.slice(start,end); this.partUpload(GUID,partFile,name,shardCount,i); } }, partUpload:function(GUID,partFile,name,chunks,chunk){ //構(gòu)造一個表單,F(xiàn)ormData是HTML5新增的 var now = this; var form = new FormData(); form.append("guid", GUID); form.append("file", partFile); //slice方法用于切出文件的一部分 form.append("fileName", name); form.append("chunks", chunks); //總片數(shù) form.append("chunk", chunk); //當前是第幾片 //Ajax提交 $.ajax({ url: "http://localhost:8080/api/upload/part", type: "POST", data: form, async: true, //異步 processData: false, //很重要,告訴jquery不要對form進行處理 contentType: false, //很重要,指定為false才能形成正確的Content-Type success: function(data){ status++; if(data.code == 200){ $("#output").html(status+ " / " + chunks); } if(status==chunks){ now.mergeFile(GUID,name); } } }); }, mergeFile:function(GUID,name){ var formMerge = new FormData(); formMerge.append("guid", GUID); formMerge.append("fileName", name); $.ajax({ url: "http://localhost:8080/api/upload/merge", type: "POST", data: formMerge, processData: false, //很重要,告訴jquery不要對form進行處理 contentType: false, //很重要,指定為false才能形成正確的Content-Type success: function(data){ if(data.code == 200){ alert('上傳成功!'); } } }); }, guid:function(prefix){ var counter = 0; var guid = (+new Date()).toString( 32 ), i = 0; for ( ; i < 5; i++ ) { guid += Math.floor( Math.random() * 65535 ).toString( 32 ); } return (prefix || 'wu_') + guid + (counter++).toString( 32 ); } }; $(function(){ page.init(); }); </script></html>
3.優(yōu)化
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
說明:
設置的數(shù)值雖好比前端傳過來的大,要不容易報錯
上述內(nèi)容就是springboot中怎么實現(xiàn)切割分片上傳功能,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章題目:springboot中怎么實現(xiàn)切割分片上傳功能
分享網(wǎng)址:http://bm7419.com/article20/pcecjo.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供關鍵詞優(yōu)化、自適應網(wǎng)站、云服務器、營銷型網(wǎng)站建設、定制開發(fā)、響應式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)