开发者

Java断点续传(文件分块)完整实现步骤

开发者 https://www.devze.com 2025-05-23 10:24 出处:网络 作者: 破晓*
目录什么是断点续传?简要概述实现步骤:先进行大文件资源 分块操作:1.导入一系列的包2.定义相关的类和方法3.创建分块文件 4.对大文件分成文件块5.进行对文件的读取写入再进行分块文件 合并操作:总结 什
目录
  • 什么是断点续传?
  • 简要概述实现步骤:
  • 先进行大文件资源 分块操作:
    • 1.导入一系列的包
    • 2.定义相关的类和方法
    • 3.创建分块文件
    •  4.对大文件分成文件块
    • 5.进行对文件的读取写入
  • 再进行分块文件 合并操作:
    • 总结 

      什么是断点续传?

      引用百度百科:对断点续传的定义

      Java断点续传(文件分块)完整实现步骤

      个人理解:如果我们要在项目的媒资管理部分,上传视频文件(通常这类视频文件都比较大),http协议本身对上传文件大小没有限制,但是客户的网络环境质量,电脑硬件环境参差不齐,可能会导致一个大文件快上传完了出现断网的情况,从而导致文件没有上传成功,需要客户重新上传,用户体验非常差,所以对于大文件上传的要求是能做到 断点续传

      断点续传流程图如下图:

      Java断点续传(文件分块)完整实现步骤

      简要概述实现步骤:

      • 前端上传完先把文件分成块
      • 一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传
      • 各分块上传完成最后在服务端合并文件

      (为了方便理解,我用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)!

      0

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      关注公众号