這篇文章主要介紹“如何使用vue+springboot上傳大文件”的相關(guān)知識(shí),小編通過實(shí)際案例向大家展示操作過程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“如何使用vue+springboot上傳大文件”文章能幫助大家解決問題。
公司主營(yíng)業(yè)務(wù):網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)推出尼元陽(yáng)免費(fèi)做網(wǎng)站回饋大家。
需要做大文件上傳應(yīng)該考慮到如下邏輯:
大文件上傳一般需要將文件切片(chunk)上傳,然后再將所有切片合并為完整的文件??梢园匆韵逻壿嬤M(jìn)行實(shí)現(xiàn):
前端在頁(yè)面中選擇要上傳的文件,并使用Blob.slice方法對(duì)文件進(jìn)行切片,一般每個(gè)切片大小為固定值(比如5MB),并記錄總共有多少個(gè)切片。
將切片分別上傳到后端服務(wù),可以使用XMLHttpRequest或Axios等庫(kù)發(fā)送Ajax請(qǐng)求。對(duì)于每個(gè)切片,需要包含三個(gè)參數(shù):當(dāng)前切片索引(從0開始)、切片總數(shù)、切片文件數(shù)據(jù)。
后端服務(wù)接收到切片后,保存到指定路徑下的臨時(shí)文件中,并記錄已上傳的切片索引和上傳狀態(tài)。如果某個(gè)切片上傳失敗,則通知前端重傳該切片。
當(dāng)所有切片都上傳成功后,后端服務(wù)讀取所有切片內(nèi)容并將其合并為完整的文件??梢允褂胘ava.io.SequenceInputStream和BufferedOutputStream來實(shí)現(xiàn)文件合并。
最后返回文件上傳成功的響應(yīng)結(jié)果給前端即可。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>File Upload</title> </head> <body> <input type="file" id="fileInput"> <button onclick="upload()">Upload</button> <script> function upload() { let file = document.getElementById("fileInput").files[0]; let chunkSize = 5 * 1024 * 1024; // 切片大小為5MB let totalChunks = Math.ceil(file.size / chunkSize); // 計(jì)算切片總數(shù) let index = 0; while (index < totalChunks) { let chunk = file.slice(index * chunkSize, (index + 1) * chunkSize); let formData = new FormData(); formData.append("file", chunk); formData.append("index", index); formData.append("totalChunks", totalChunks); // 發(fā)送Ajax請(qǐng)求上傳切片 $.ajax({ url: "/uploadChunk", type: "POST", data: formData, processData: false, contentType: false, success: function () { if (++index >= totalChunks) { // 所有切片上傳完成,通知服務(wù)端合并文件 $.post("/mergeFile", {fileName: file.name}, function () { alert("Upload complete!"); }) } } }); } } </script> </body> </html>
controller層:
@RestController public class FileController { @Value("${file.upload-path}") private String uploadPath; @PostMapping("/uploadChunk") public void uploadChunk(@RequestParam("file") MultipartFile file, @RequestParam("index") int index, @RequestParam("totalChunks") int totalChunks) throws IOException { // 以文件名+切片索引號(hào)為文件名保存切片文件 String fileName = file.getOriginalFilename() + "." + index; Path tempFile = Paths.get(uploadPath, fileName); Files.write(tempFile, file.getBytes()); // 記錄上傳狀態(tài) String uploadFlag = UUID.randomUUID().toString(); redisTemplate.opsForList().set("upload:" + fileName, index, uploadFlag); // 如果所有切片已上傳,則通知合并文件 if (isAllChunksUploaded(fileName, totalChunks)) { sendMergeRequest(fileName, totalChunks); } } @PostMapping("/mergeFile") public void mergeFile(String fileName) throws IOException { // 所有切片均已成功上傳,進(jìn)行文件合并 List<File> chunkFiles = new ArrayList<>(); for (int i = 0; i < getTotalChunks(fileName); i++) { String chunkFileName = fileName + "." + i; Path tempFile = Paths.get(uploadPath, chunkFileName); chunkFiles.add(tempFile.toFile()); } Path destFile = Paths.get(uploadPath, fileName); try (OutputStream out = Files.newOutputStream(destFile); SequenceInputStream seqIn = new SequenceInputStream(Collections.enumeration(chunkFiles)); BufferedInputStream bufIn = new BufferedInputStream(seqIn)) { byte[] buffer = new byte[1024]; int len; while ((len = bufIn.read(buffer)) > 0) { out.write(buffer, 0, len); } } // 清理臨時(shí)文件和上傳狀態(tài)記錄 for (int i = 0; i < getTotalChunks(fileName); i++) { String chunkFileName = fileName + "." + i; Path tempFile = Paths.get(uploadPath, chunkFileName); Files.deleteIfExists(tempFile); redisTemplate.delete("upload:" + chunkFileName); } } private int getTotalChunks(String fileName) { // 根據(jù)文件名獲取總切片數(shù) return Objects.requireNonNull(Paths.get(uploadPath, fileName).toFile().listFiles()).length; } private boolean isAllChunksUploaded(String fileName, int totalChunks) { // 判斷所有切片是否已都上傳完成 List<String> uploadFlags = redisTemplate.opsForList().range("upload:" + fileName, 0, -1); return uploadFlags != null && uploadFlags.size() == totalChunks; } private void sendMergeRequest(String fileName, int totalChunks) { // 發(fā)送合并文件請(qǐng)求 new Thread(() -> { try { URL url = new URL("http://localhost:8080/mergeFile"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); OutputStream out = conn.getOutputStream(); String query = "fileName=" + fileName; out.write(query.getBytes()); out.flush(); out.close(); BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); while (br.readLine() != null) ; br.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } @Autowired private RedisTemplate<String, Object> redisTemplate; }
其中,file.upload-path為文件上傳的保存路徑,可以在application.properties或application.yml中進(jìn)行配置。同時(shí)需要添加RedisTemplate的Bean以便記錄上傳狀態(tài)。
如果需要使用RedisTemplate,需要引入下方的包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
同時(shí)在yml配置redis的信息
spring.redis.host=localhost spring.redis.port=6379 spring.redis.database=0
然后在自己的類中這樣使用
@Component public class myClass { @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } }
注意事項(xiàng)
需要控制每次上傳的切片大小,以兼顧上傳速度和穩(wěn)定性,避免占用過多服務(wù)器資源或因網(wǎng)絡(luò)不穩(wěn)定而導(dǎo)致上傳失敗。
切片上傳存在先后順序,需要保證所有切片都上傳完成后再進(jìn)行合并,否則可能會(huì)出現(xiàn)文件不完整或者文件合并錯(cuò)誤等情況。
上傳完成后需要及時(shí)清理臨時(shí)文件,避免因?yàn)檎加眠^多磁盤空間而導(dǎo)致服務(wù)器崩潰??梢栽O(shè)置一個(gè)定期任務(wù)來清理過期的臨時(shí)文件。
關(guān)于“如何使用vue+springboot上傳大文件”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
本文標(biāo)題:如何使用vue+springboot上傳大文件
文章來源:http://m.rwnh.cn/article48/jcjeep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司、云服務(wù)器、建站公司、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)