這篇文章將為大家詳細講解有關(guān)如何實現(xiàn)springboot帶有進度條的上傳功能,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名申請、網(wǎng)絡(luò)空間、營銷軟件、網(wǎng)站建設(shè)、廊坊網(wǎng)站維護、網(wǎng)站推廣。
具體如下:
一、說明
最近要做文件上傳,在網(wǎng)上找了很久都沒有一個全面的示例,特此記錄下來分享給大家。
1.文件上傳接口可按照springboot默認實現(xiàn),也可用commons-fileupload組件,本示例使用springboot默認文件上傳 2.最后也有commons-fileupload組件接口示例
2.重點在前端JS實現(xiàn)(也可以使用ajax上傳),參考了網(wǎng)上大量上傳文件顯示進度條博客以及技術(shù)方案,在此做了一個統(tǒng)一的總結(jié),方便后續(xù)使用
3.這僅僅是一個示例,大家可根據(jù)實際需要改進。
二、前端代碼
文件上傳
0KB/s
三、對上傳代碼進行組件化封裝
UploadCommon.js
/** * 上傳文件公共組件 * * @param url 上傳地址 * @param processBar 進度條 jquery獲取的頁面組件 * @param speedLab 顯示上傳速度Label jquery獲取的頁面組件 * @param uploadBtn 上傳按鈕 jquery獲取的頁面組件 * @param cancelBtn 取消上傳按鈕 jquery獲取的頁面組件 * @param callBack 上傳完成回調(diào)函數(shù) 上傳完成后的回調(diào)函數(shù),可以不傳 * @author * @returns */function UploadCommon(url, processBar, speedLab, uploadBtn, cancelBtn, callBack){ function init() { // 每次回調(diào)監(jiān)測上傳開始時間 var startTime = null // 已上傳文件大小 var oloaded = null var xhr = new XMLHttpRequest() function setProgress(w) { processBar.width(w + '%'); processBar.text(w + '%'); } function progressMonitor(evt){ if (evt.lengthComputable) { var completePercent = Math.round(evt.loaded / evt.total * 100) setProgress(completePercent) var nowTime = new Date().getTime() // 計算出上次調(diào)用該方法時到現(xiàn)在的時間差,單位為s var pertime = (nowTime - startTime) / 1000 // 重新賦值時間,用于下次計算 startTime = new Date().getTime() // 計算該分段上傳的文件大小,單位b var perload = evt.loaded - oloaded // 重新賦值已上傳文件大小,用以下次計算 oloaded = evt.loaded // 上傳速度計算,單位b/s var speed = perload / pertime var bspeed = speed // 單位名稱 var units = 'bit/s'if (speed / 1024 > 1) { speed = speed / 1024 units = 'Kb/s' } if (speed / 1024 > 1) { speed = speed / 1024 units = 'Mb/s' } speed = speed.toFixed(1); // 剩余時間 var resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1) speedLab.html(speed + units + ',剩余時間:' + resttime + 's') } } // 上傳成功后回調(diào) function uploadComplete(evt) { uploadBtn.attr('disabled', false) var status = evt.currentTarget.status if (status == 401) { alert('請登錄后再上傳') return } if (status == 403) { alert('無權(quán)限操作') return } if (status != 200) { alert('上傳異常,錯誤碼' + status) return } var response=JSON.parse(evt.currentTarget.response) if (response.code!='200') { alert('上傳處理異常' + response.msg) return } console.log('上傳成功') if ( callBack != null && typeof callBack != 'undefined') { callBack() } }; // 上傳失敗回調(diào) function uploadFailed(evt) { alert('上傳處理失敗' + evt.target.responseText) } // 終止上傳 function cancelUpload() { xhr.abort() } // 上傳取消后回調(diào) function uploadCanceled(evt) { alert('文件上傳已終止:' + evt.target.responseText) } // 添加取消上傳事件 cancelBtn.click(function() { uploadBtn.attr('disabled', false) cancelUpload(); }) this.uploadFile = function(formData) { // 上傳按鈕禁用 uploadBtn.attr('disabled', true); setProgress(0) // true為異步處理 xhr.open('post', url, true) // 上傳開始執(zhí)行方法 xhr.onloadstart = function() { console.log('開始上傳') // 設(shè)置上傳開始時間 startTime = new Date().getTime() // 已上傳的文件大小為0 oloaded = 0 } xhr.upload.addEventListener('progress', progressMonitor, false) xhr.addEventListener("load", uploadComplete, false) xhr.addEventListener("error", uploadFailed, false) xhr.addEventListener("abort", uploadCanceled, false) xhr.send(formData); } this.setProgressValue=function(w){ processBar.width(w + '%') processBar.text(w + '%') } } return new init()}
調(diào)用
$(document).ready(function() { var addVersionBtn=$('#addVersionBtn') //
四,服務(wù)端接口
1.springboot默認實現(xiàn)
pom.xml
4.0.0 com.demo demo 0.0.1-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.5.10.RELEASE UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-devtools true org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-thymeleaf net.sourceforge.nekohtml nekohtml org.springframework.boot spring-boot-starter-test test io.springfox springfox-swagger2 2.7.0 io.springfox springfox-swagger-ui 2.7.0 org.springframework.boot spring-boot-maven-plugin
application.yml
server: port: 8080 tomcat: uri-encoding: UTF-8 application: name: demo thymeleaf: encoding: UTF-8 cache: true mode: LEGACYHTML5 devtools: restart: enabled: true http: multipart: maxFileSize: 500Mb maxRequestSize: 500Mb location: D:/tmpdebug: false
接口:
@PostMapping("/upload")public String uploadFile(@RequestParam("file") MultipartFile file) { if (file == null || file.isEmpty()) { return "file is empty"; } // 獲取文件名 String fileName = file.getOriginalFilename(); // 文件存儲路徑 String filePath = "D:/data/" + UUID.randomUUID().toString().replaceAll("-", "") + "_" + fileName; logger.info("save file to:" + filePath); File dest = new File(filePath); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); return "success"; } catch (Exception e) { e.printStackTrace(); } return "fail"; }
啟動類
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.builder.SpringApplicationBuilder;import org.springframework.boot.web.support.SpringBootServletInitializer;import org.springframework.transaction.annotation.EnableTransactionManagement;@SpringBootApplication@EnableTransactionManagementpublic class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
2.使用commons-fileupload上傳組件
application.yml
server: port: 8080 tomcat: uri-encoding : UTF-8spring: application: name: svc-demo thymeleaf: encoding: UTF-8 cache: false mode: LEGACYHTML5debug: false
pom .xml
進程類
public class Progress{ private long bytesRead; //已讀取文件的比特數(shù) private long contentLength;//文件總比特數(shù) private long items; //正讀的第幾個文件 public long getBytesRead(){ return bytesRead; } public void setBytesRead(long bytesRead){ this.bytesRead = bytesRead; } public long getContentLength() { return contentLength; } public void setContentLength(long contentLength) { this.contentLength = contentLength; } public long getItems() { return items; } public void setItems(long items)\{ this.items = items; }}
監(jiān)聽類
@Componentpublic class FileUploadProgressListener implements ProgressListener{ private HttpSession session; public void setSession(HttpSession session){ this.session=session; Progress status = new Progress();//保存上傳狀態(tài) session.setAttribute("status", status); } @Override public void update(long bytesRead, long contentLength, int items) { Progress status = (Progress) session.getAttribute("status"); status.setBytesRead(bytesRead); status.setContentLength(contentLength); status.setItems(items); }}
文件上傳處理類
public class CustomMultipartResolver extends CommonsMultipartResolver{ // 注入第二步寫的FileUploadProgressListener @Autowired private FileUploadProgressListener progressListener; public void setFileUploadProgressListener(FileUploadProgressListener progressListener){ this.progressListener = progressListener; } @Override public MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException{ String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); //fileUpload.setFileSizeMax(1024 * 1024 * 500);// 單個文件最大500M //fileUpload.setSizeMax(1024 * 1024 * 500);// 一次提交總文件最大500M progressListener.setSession(request.getSession());// 問文件上傳進度監(jiān)聽器設(shè)置session用于存儲上傳進度 fileUpload.setProgressListener(progressListener);// 將文件上傳進度監(jiān)聽器加入到 fileUpload 中 try{ List
控制器
@RestControllerpublic class FileController{ @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { return "文件為空"; } // 獲取文件名 String fileName = file.getOriginalFilename();// 文件上傳后的路徑 // 文件上傳后的路徑 String filePath = null; try{ filePath = new File("").getCanonicalPath() + "/tmp/uploadFile/"; } catch (IOException e){ e.printStackTrace(); } //存儲路徑 String tagFilePath = filePath + CommonUtil.getCurrentTime() + fileName; File dest = new File(tagFilePath); // 檢測是否存在目錄 if (!dest.getParentFile().exists()){ dest.getParentFile().mkdirs(); } try{ file.transferTo(dest); } catch (IllegalStateException e){ e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } return fileName + "上傳失敗"; }}
啟動類
//注意取消自動Multipart配置,否則可能在上傳接口中拿不到file的值@EnableAutoConfiguration(exclude = { MultipartAutoConfiguration.class })@SpringBootApplicationpublic class Application extends SpringBootServletInitializer{ //注入自定義的文件上傳處理類 @Bean(name = "multipartResolver") public MultipartResolver multipartResolver() { CustomMultipartResolver customMultipartResolver = new CustomMultipartResolver(); return customMultipartResolver; } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application){ return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); }
關(guān)于“如何實現(xiàn)springboot帶有進度條的上傳功能”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。