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

 更新时间:2025年05月22日 10:14:25   作者:破晓*  
这篇文章主要介绍了Java断点续传(文件分块)完整实现步骤, 断点续传通过分块传输大文件,中断后可续传未完成部分,服务端合并分块,避免重复上传,提升用户体验并节省网络资源,文中通过代码介绍的非常详细,需要的朋友可以参考下

什么是断点续传?

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

个人理解:如果我们要在项目的媒资管理部分,上传视频文件(通常这类视频文件都比较大),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()表示返回目录中所有文件和子目录的File数组,files是包含所有分块文件的数组
File[] files = chunkFolder.listFiles();
//将数组转换为list集合,fileList是包含所以分块文件的list<File>
List<File> fileList = Arrays.asList(files);
//然后对List进行排序,Comparator.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 len;
    while ((len = raf_read.read(buffer)) != -1) {  
        raf_write.write(buffer, 0, len);  
    }
    raf_read.close();  // 关闭分块文件流
}
raf_write.close();  // 关闭合并文件流

这段代码遍历分块文件列表,并以只读模式打开分块文件,然后读取分块文件内容并写入到合并文件,最后关闭分块文件流和合并文件流

这里我再总结一下掌握断点续传的技术,我们能够将多个分块文件合并成一个完整文件,避免用户在下载过程因为网络,系统等一系列原因导致下载中断,而需重新开始下载的情况。而是可以直接从中断处继续下载,节省了我们时间和网络资源

总结 

到此这篇关于Java断点续传(文件分块)实现的文章就介绍到这了,更多相关Java断点续传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java线性结构中栈、队列和串的基本概念和特点详解

    Java线性结构中栈、队列和串的基本概念和特点详解

    前几天小编给大家介绍了Java线性结构中的链表,除了链表这种结构之外,实际上还有栈、队列、串等结构,那么这些结构又有哪些特点呢,本文就给大家详细的介绍一下,感兴趣的小伙伴跟着小编一起来看看吧
    2023-07-07
  • java实现文件上传下载和图片压缩代码示例

    java实现文件上传下载和图片压缩代码示例

    本文给大家介绍的是项目中经常需要用到的一个常用的功能,使用java实现文件的上传下载和图片的压缩功能,这里推荐给大家,有需要的小伙伴参考下。
    2015-03-03
  • java中replaceAll替换圆括号实例代码

    java中replaceAll替换圆括号实例代码

    正则表达式的保留字符主要有:圆括号、方括号、花括号、竖线、横线、点号、加号、星号、反斜杆等等,下面这篇文章主要给大家介绍了关于java中replaceAll替换圆括号的相关资料,需要的朋友可以参考下
    2022-10-10
  • SpringCloud升级2020.0.x版之OpenFeign简介与使用实现思路

    SpringCloud升级2020.0.x版之OpenFeign简介与使用实现思路

    在微服务系统中,我们经常会进行 RPC 调用。在 Spring Cloud 体系中,RPC 调用一般就是 HTTP 协议的调用。对于每次调用,都要经过一系列详细步骤,接下来通过本文给大家介绍SpringCloud OpenFeign简介与使用,感兴趣的朋友一起看看吧
    2021-10-10
  • Mybatis Plus使用@TableId之坑及解决

    Mybatis Plus使用@TableId之坑及解决

    这篇文章主要介绍了Mybatis Plus使用@TableId之坑及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 使用kotlin集成springboot开发的超详细教程

    使用kotlin集成springboot开发的超详细教程

    目前大多数都在使用java集成 springboot进行开发,本文演示仅仅将 java换成 kotlin,其他不变的情况下进行开发,需要的朋友可以参考下
    2021-09-09
  • 在idea2023中使用SpringBoot整合Lombok全过程及详细用法

    在idea2023中使用SpringBoot整合Lombok全过程及详细用法

    Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能,本文详细给大家介绍了在idea2023中使用SpringBoot整合Lombok全过程及详细用法,需要的朋友可以参考下
    2023-09-09
  • 详解Mybatis的分页插件

    详解Mybatis的分页插件

    这篇文章主要介绍了详解Mybatis的分页插件,在 Mybatis中,如何对数据进行分页是一个非常常见的问题,现在,我们可以通过使用 Mybatis 的分页插件来实现对数据的分页,需要的朋友可以参考下
    2023-05-05
  • Spring Cache和EhCache实现缓存管理方式

    Spring Cache和EhCache实现缓存管理方式

    这篇文章主要介绍了Spring Cache和EhCache实现缓存管理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java中SpringBoot自定义Starter详解

    Java中SpringBoot自定义Starter详解

    这篇文章主要介绍了Java中SpringBoot自定义Starter详解,Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境进行自动配置,需要的朋友可以参考下
    2023-07-07

最新评论