Java斷點(diǎn)續(xù)傳(文件分塊)完整實(shí)現(xiàn)步驟
什么是斷點(diǎn)續(xù)傳?
引用百度百科:對(duì)斷點(diǎn)續(xù)傳的定義
個(gè)人理解:如果我們要在項(xiàng)目的媒資管理部分,上傳視頻文件(通常這類視頻文件都比較大),http協(xié)議本身對(duì)上傳文件大小沒(méi)有限制,但是客戶的網(wǎng)絡(luò)環(huán)境質(zhì)量,電腦硬件環(huán)境參差不齊,可能會(huì)導(dǎo)致一個(gè)大文件快上傳完了出現(xiàn)斷網(wǎng)的情況,從而導(dǎo)致文件沒(méi)有上傳成功,需要客戶重新上傳,用戶體驗(yàn)非常差,所以對(duì)于大文件上傳的要求是能做到 斷點(diǎn)續(xù)傳
斷點(diǎn)續(xù)傳流程圖如下圖:
簡(jiǎn)要概述實(shí)現(xiàn)步驟:
- 前端上傳完先把文件分成塊
- 一塊一塊的上傳,上傳中斷后重新上傳,已上傳的分塊則不用再上傳
- 各分塊上傳完成最后在服務(wù)端合并文件
(為了方便理解,我用Java代碼的方法 測(cè)試文件的分塊與合并)
先進(jìn)行大文件資源 分塊操作:
1.導(dǎo)入一系列的包
package com.xuecheng.media; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.util.*;
導(dǎo)入多個(gè)外部和Java自帶的庫(kù),其中org.apache.commons.codec.digest.DigestUtils:用于生成文章的摘要,能夠在斷點(diǎn)續(xù)傳中驗(yàn)證文件的完整性
2.定義相關(guān)的類和方法
public class BigFileTest { //測(cè)試文件分塊方法 @Test public void testChunk() throws IOException {
定義一個(gè)公共類BigFileTest,用于包含文件處理相關(guān)的測(cè)試方法,并且定義了一個(gè)testChunk方法,該方法用于執(zhí)行文件分塊操作,并聲明了可能拋出IOException異常,因?yàn)槲募僮骺赡軙?huì)失敗
3.創(chuàng)建分塊文件
File sourceFile = new File("d:/develop/bigfile_test/nacos.mp4"); String chunkPath = "d:/develop/bigfile_test/chunk/"; File chunkFolder = new File(chunkPath); if (!chunkFolder.exists()) { chunkFolder.mkdirs(); }
創(chuàng)建一個(gè)File對(duì)象,表示要對(duì)d:/develop/bigfile_test/路徑下的nacos.mp4源文件進(jìn)行分塊,并創(chuàng)建一個(gè)File對(duì)象,表示分塊存儲(chǔ)的文件夾,如果分塊文件夾不存在,則創(chuàng)建它
4.對(duì)大文件分成文件塊
//分塊大小 long chunkSize = 1024 * 1024 * 1; //分塊數(shù)量 long chunkNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkSize); System.out.println("分塊總數(shù):" + chunkNum);
然后對(duì) 文件進(jìn)行分割,定義每個(gè)分塊的大小,通過(guò)源文件的長(zhǎng)度除以分塊大小(要采用向上取整噢)使用Math.ceil方法向上取整,計(jì)算出分塊的總數(shù)
5.進(jìn)行對(duì)文件的讀取寫入
//緩沖區(qū)大小 byte[] b = new byte[1024]; //使用RandomAccessFile訪問(wèn)文件 RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r"); //分塊 for (int i = 0; i < chunkNum; i++) { //創(chuàng)建分塊文件 File file = new File(chunkPath + i); if (file.exists()) { file.delete(); } boolean newFile = file.createNewFile(); if (newFile) { //向分塊文件中寫數(shù)據(jù) RandomAccessFile raf_write = new RandomAccessFile(file, "rw"); int len = -1; while ((len = raf_read.read(b))!= -1) { raf_write.write(b, 0, len); if (file.length() >= chunkSize) { break; } } raf_write.close(); System.out.println("完成分塊" + i); } } raf_read.close();
然后進(jìn)行緩沖區(qū)與文件讀取寫入,以上代碼塊創(chuàng)建了一個(gè)大小為1024字節(jié)的緩沖區(qū)數(shù)組b,用于讀取源文件數(shù)據(jù),并且以只讀模式打開(kāi)源文件,然后進(jìn)行分塊操作
循環(huán)分塊數(shù)量chunkNum(對(duì)源文件進(jìn)行分塊后得到的分塊總數(shù)),if循環(huán)判斷分塊文件是否創(chuàng)建成功,如果創(chuàng)建成功,則從源文件中讀取數(shù)據(jù)到緩沖區(qū),直到讀取到文件末尾
再進(jìn)行分塊文件 合并操作:
各個(gè)文件塊讀取完畢后,就可以進(jìn)行 文件合并 操作,分塊合并步驟
File chunkFolder = new File("D:\\...\\chunk\\"); // 分塊文件目錄 File sourceFile = new File("D:\\...\\星際牛仔1.mp4"); // 原始文件 File mergeFile = new File("D:\\...\\星際牛仔1-1.mp4"); // 合并后的文件 mergeFile.createNewFile(); // 創(chuàng)建空的目標(biāo)文件
定義分塊文件的存儲(chǔ)目錄,原始文件路徑和合并后的文件路徑,并創(chuàng)建一個(gè)空的目標(biāo)文件
RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw"); // 以讀寫模式打開(kāi)合并文件 byte[] buffer = new byte[1024]; // 讀寫緩沖區(qū)(1KB)
初始化寫入流,RandomAccessFile是一個(gè)用于隨機(jī)訪問(wèn)文件的類,適合大文件操作,“rw”表示讀寫模式,byte[ ] buffer = new byte[1024]這段代碼創(chuàng)建了一個(gè)字節(jié)數(shù)組,作為讀寫緩沖區(qū)(臨時(shí)存儲(chǔ)從文件或網(wǎng)絡(luò)中讀取的數(shù)據(jù)),每次讀取1KB數(shù)據(jù),減少磁盤I/O次數(shù)
//listFiles()表示返回目錄中所有文件和子目錄的File數(shù)組,files是包含所有分塊文件的數(shù)組 File[] files = chunkFolder.listFiles(); //將數(shù)組轉(zhuǎn)換為list集合,fileList是包含所以分塊文件的list<File> List<File> fileList = Arrays.asList(files); //然后對(duì)List進(jìn)行排序,Comparator.comparingInt創(chuàng)建一個(gè)比較器,按照指定規(guī)則排序(將文件名轉(zhuǎn)換為整數(shù)進(jìn)行排序) Collections.sort(fileList, Comparator.comparingInt(o -> Integer.parseInt(o.getName())));
對(duì)分塊文件進(jìn)行排序,o -> Integer.parseInt(o.getName()):是一個(gè)Lambda表達(dá)式,用于將文件名轉(zhuǎn)換為整數(shù)進(jìn)行排序
//循環(huán)遍歷分塊文件列表 for (File chunkFile : fileList) { //以只讀模式打開(kāi)分塊文件 "r"表示以只讀模式打開(kāi) RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "r"); //讀取分塊文件內(nèi)容并寫入合并文件 int len; while ((len = raf_read.read(buffer)) != -1) { raf_write.write(buffer, 0, len); } raf_read.close(); // 關(guān)閉分塊文件流 } raf_write.close(); // 關(guān)閉合并文件流
這段代碼遍歷分塊文件列表,并以只讀模式打開(kāi)分塊文件,然后讀取分塊文件內(nèi)容并寫入到合并文件,最后關(guān)閉分塊文件流和合并文件流
這里我再總結(jié)一下掌握斷點(diǎn)續(xù)傳的技術(shù),我們能夠?qū)⒍鄠€(gè)分塊文件合并成一個(gè)完整文件,避免用戶在下載過(guò)程因?yàn)榫W(wǎng)絡(luò),系統(tǒng)等一系列原因?qū)е孪螺d中斷,而需重新開(kāi)始下載的情況。而是可以直接從中斷處繼續(xù)下載,節(jié)省了我們時(shí)間和網(wǎng)絡(luò)資源
總結(jié)
到此這篇關(guān)于Java斷點(diǎn)續(xù)傳(文件分塊)實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java斷點(diǎn)續(xù)傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中使用Guava實(shí)現(xiàn)單機(jī)令牌桶限流的示例
本文主要介紹了SpringBoot中使用Guava實(shí)現(xiàn)單機(jī)令牌桶限流的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06利用Java實(shí)現(xiàn)調(diào)用http請(qǐng)求
在實(shí)際開(kāi)發(fā)過(guò)程中,我們經(jīng)常需要調(diào)用對(duì)方提供的接口或測(cè)試自己寫的接口是否合適。本文就為大家準(zhǔn)備了幾個(gè)java調(diào)用http請(qǐng)求的幾種常見(jiàn)方式,需要的可以參考一下2022-08-08maven項(xiàng)目無(wú)法讀取到resource文件夾的問(wèn)題
這篇文章主要介紹了maven項(xiàng)目無(wú)法讀取到resource文件夾的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11使用mybatis的interceptor修改執(zhí)行sql以及傳入?yún)?shù)方式
這篇文章主要介紹了使用mybatis的interceptor修改執(zhí)行sql以及傳入?yún)?shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Springboot中實(shí)現(xiàn)接口冪等性的4種方案小結(jié)
本文主要介紹了Springboot中實(shí)現(xiàn)接口冪等性,包含數(shù)據(jù)庫(kù)的冪等,數(shù)據(jù)庫(kù)的冪等,Redis的冪等性和Token + 時(shí)間戳的冪等性,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03SpringBoot Tomcat啟動(dòng)實(shí)例代碼詳解
這篇文章主要介紹了SpringBoot Tomcat啟動(dòng)實(shí)例代碼詳解,需要的朋友可以參考下2017-09-09可視化定時(shí)任務(wù)quartz集成解析全過(guò)程
在開(kāi)發(fā)中有很多定時(shí)任務(wù)都不是寫死的而是可以人為配置并且寫到數(shù)據(jù)庫(kù)中的,下面這篇文章主要給大家介紹了關(guān)于可視化定時(shí)任務(wù)quartz集成解析的相關(guān)資料,需要的朋友可以參考下2022-10-10解決異常FileNotFoundException:class path resource找不到資源文件的問(wèn)題
今天小編就為大家分享一篇關(guān)于解決異常FileNotFoundException:class path resource找不到資源文件的問(wèn)題,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12