目录
- 什么是断点续传?
- 简要概述实现步骤:
- 先进行大文件资源 分块操作:
- 1.导入一系列的包
- 2.定义相关的类和方法
- 3.创建分块文件
- 4.对大文件分成文件块
- 5.进行对文件的读取写入
- 再进行分块文件 合并操作:
- 总结
什么是断点续传?
引用百度百科:对断点续传的定义
个人理解:如果我们要在项目的媒资管理部分,上传视频文件(通常这类视频文件都比较大),http协议本身对上传文件大小没有限制,但是客户的网络环境质量,电脑硬件环境参差不齐,可能会导致一个大文件快上传完了出现断网的情况,从而导致文件没有上传成功,需要客户重新上传,用户体验非常差,所以对于大文件上传的要求是能做到 断点续传
断点续传流程图如下图:
简要概述实现步骤:
- 前端上传完先把文件分成块
- 一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传
- 各分块上传完成最后在服务端合并文件
(为了方便理解,我用Java代码的方法 测试文件的分块与合并)
先进行大文件资源 分块操作:
1.导入一系列的包
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.*;
导入多个外部和Java自带的库,其中org.apache.commons.codec.digest.DigestUtils:用于生成文章的摘要,能够在断点续传中验证文件的完整性
2.定义相关的类和方法
public class BigFileTest { //测试文件分块方法 @Test public void testChunk() throws IOException {
定义一个公共类BigFileTest,用于包含文件处理相关的测试方法,并且定义了一个testChunk方法,该方法用于执行文件分块操作,并声明了可能抛出IOException异常,因为文件操作可能会失败
3.创建分块文件
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(); }
创建一个File对象,表示要对d:/develop/bigfile_test/路径下的nacos.mp4源文件进行分块,并创建一个File对象,表示分块存储的文件夹,如果分块文件夹不存在,则创建它
4.对大文件分成文件块
//分块大小 long chunkSize = 1024 * 1024 * 1; //分块数量 long chunkNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkSize); System.out.println("分块总数:" + chunkNum);
然后对 文件进行分割,定义每个分块的大小,通过源文件的长度除以分块大小(要采用向上取整噢)使用Math.ceil方法向上取整,计算出分块的总数
5.进行对文件的读取写入
//缓冲区大小 byte[] b = new byte[1024]; //使用RandoMACcessFile访问文件 RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r"); //分块 for (int i = 0; i < chunkNum; i++) { //创建分块文件 File file = new File(chunkPath + i); if (file.exists()) { file.delete(); } boolean newFile = file.createNewFile(); if (newFile) { //向分块文件中写数据 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();
然后进行缓冲区与文件读取写入,以上代码块创建了一个大小为1024字节的缓冲区数组b,用于读取源文件数据,并且以只读模式打开源文件,然后进行分块操作
循环分块数量chunkNum(对源文件进行分块后得到的分块总数),if循环判断分块文件是否创建成功,如果创建成功,则从源文件中读取数据到缓冲区,直到读取到文件末尾
再进行分块文件 合并操作:
各个文件块读取完毕后,就可以进行 文件合并 操作,分块合并步骤
File chunkFolder = new File("D:\\...\\chunk\\"); // 分块文件目录 File sourceFile = new File("D:\\...\\星际牛仔1.mp4"); // 原始文件 File mergeFile = new File("D:\\...\\星际牛仔1-1.mp4"); // 合并后的文件 mergeFile.createNewFile(); // 创建空的目标文件
定义分块文件的存储目录,原始文件路径和合并后的文件路径,并创建一个空的目标文件
RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw"); // 以读写模式打开合并文件 byte[] buffer = new byte[1024]; // 读写缓冲区(1KB)
初始化写入流,RandomAccessFile是一个用于随机访问文件的类,适合大文件操作,“rw”表示读写模式,byte[ ] buffer = new byte[1024]这段代码创建了一个字节数组,作为读写缓冲区(临时存储从文件或网络中读取的数据),每次读取1KB数据,减少磁盘I/O次数
//listFiles()表示返回目录中android所有文件和子目录的File数组,files是包含所有分块文件的数组 File[] files = chunkFolder.listFiles(); //将数组转换为list集合,fileList是包含所以分块文件的list<File> List<File> fileList = Arrays.asList(files); //然后对List进行排序,Comp编程客栈arator.comparingInt创建一个比较器,按照指定规则排序(将文件名转换为整数进行排序) Collections.sort(fileList, Comparator.comparingInt(o -> Integer.parseInt(o.getName())));
对分块文件进行排序,o -> Integer.parseInt(o.getName()):是一个Lambda表达式,用于将文件名转换为整数进行排序
//循环遍历分块文件列表 for (File chunkFile : fileList) { //以只读模式打开分块文件 "r"表示以只读模式打开 RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "r"); //读取分块文件内容并写入合并文件 int lenphp; while ((len = raf_readjs.read(buffer)) != -1) { raf_write.write(buffer, 0, len); } raf_read.close(); // 关闭分块文件流 } raf_write.close(); // 关闭合并文件流
这段代码遍历分块文件列表,并以只读模式打开分块文件,然后读取分块文件内容并写入到合并文件,最后关闭分块文件流和合并文件流
这里我再总结一下掌握断点续传的技术,我们能够将多个分块文件合并成一个完整文件,避免用户在下载过程因为网络,系统等一系列原因导致下载中断,而需重新开始下载的情况。而是可以直接从中断处继续下载,节省了我们时间和网络资源
总结
到此这篇关于Java断点续传(文件分块)实现的文章就介绍到这了,更多相关Java断点续传内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以android后多多支持编程客栈(www.devze.com)!
精彩评论