断点续传实现

news2024/11/18 1:39:10

断点续传

1、 什么是断点续传

通常视频文件都比较大,所以对于媒资系统上传文件的需求要满足大文件的上传要求。http协议本身对上传文件大小没有限制,但是客户的网络环境质量、电脑硬件环境等参差不齐,如果一个大文件快上传完了网断了没有上传完成,需要客户重新上传,用户体验非常差,所以对于大文件上传的要求最基本的是断点续传。

什么是断点续传:

        引用百度百科:断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载,断点续传可以提高节省操作时间,提高用户体验性。

断点续传流程如下图:

流程如下:

1、前端上传前先把文件分成块

2、一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传

3、各分块上传完成最后在服务端合并文件

2、断点续传实现

1.前端对文件进行分块

2.前端使用多线程上传分片,上传前给服务器发送消息验证当前分片是否已经上传。

3.所有分片上传完毕后,发送合并分片请求,校验文件的完整性。 (上传的分片应该具备顺序标记)

4.前端给服务器传一个MD5值,服务器合并文件后,利用MD5值计算是否与源文件一致。如果不一致,说明文件需要重新上传。

分片文件清理问题:

  • 在数据库中有一张文件表记录minIo中存储的文件信息
  • 文件开始上传时会写入文件表,状态为上传中,上传完成会更新状态为上传完成
  • 当一个文件传了一半不再上传了,说明该文件没有上传完成,通过定时任务去查询文件表中的记录,如果文件距离上次上传结束超过24小时,则可以考虑清除MinIo中相关的分片数据

3、分块与合并测试

为了更好的理解文件分块上传的原理,下边用java代码测试文件的分块与合并。

文件分块的流程如下:

1、获取源文件长度

2、根据设定的分块文件的大小计算出块数

3、从源文件读数据依次向每一个块文件写数据。

测试代码如下:

 

package com.xuecheng.media;

import org.apache.commons.codec.digest.DigestUtils;
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.*;

/**
 * @program: xuecheng-plus-project148
 * @description: TODO大文件分块合并
 * @author: Mr.Zhang
 * @create: 2023-02-27 08:54
 **/
public class BigFileTest {

    //分块测试
    @Test
    public void testChunk() throws IOException {
        //源文件
        File sourceFile = new File("D:\\software\\Test\\xuecheng\\video\\1.mp4");

        //分块文件存储路径
        File chunkFolderPath = new File("D:\\software\\Test\\xuecheng\\chunk\\");
        if (!chunkFolderPath.exists()) {
            chunkFolderPath.mkdir();
        }

        //分块的大小   1mb
        int chunkSize = 1024 * 1024 * 1;

        //分块数量
        long chunkNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkSize);

        //思路,使用流对象读取文件,向分块文件写数据,达到分块大小不再写
        RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r");

        //缓冲区
        byte[] b = new byte[1024];
        for (long i = 0; i < chunkNum; i++) {
            //分块文件
            File file = new File("D:\\software\\Test\\xuecheng\\chunk\\" + 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();
            }
        }
        raf_read.close();
    }

    //测试合并
    @Test
    public void testMerge() throws IOException {
        //源文件
        File sourceFile = new File("D:\\software\\Test\\xuecheng\\video\\1.mp4");

        //分块文件存储路径
        File chunkFolderPath = new File("D:\\software\\Test\\xuecheng\\chunk\\");
        if (!chunkFolderPath.exists()) {
            chunkFolderPath.mkdir();
        }

        //合并后的文件
        File mergeFile = new File("D:\\software\\Test\\xuecheng\\video\\1_01.mp4");
        boolean newFile1 = mergeFile.createNewFile();

        //思路,使用流对象读取分块文件,按顺序将分块文件依次向合并文件写数据
        //获取分块文件列表,按文件名升序排序
        File[] chunkFiles = chunkFolderPath.listFiles();
        List<File> chunkFileList = Arrays.asList(chunkFiles);
        //按文件名升序排序
        Collections.sort(chunkFileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return Integer.parseInt(o1.getName()) - Integer.parseInt(o2.getName());
            }
        });
        //创建合并文件的流对象
        RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw");
        //缓冲区
        byte[] b = new byte[1024];
        for (File file : chunkFileList) {
            //读取分块文件的流对象
            RandomAccessFile raf_read = new RandomAccessFile(file, "r");
            int len = -1;
            while ((len = raf_read.read(b))!=-1){
                //向合并文件写数据
                raf_write.write(b,0,len);
            }
        }

        //校验合并后的文件是否正确
        FileInputStream sourceFileStream = new FileInputStream(sourceFile);
        FileInputStream mergeFileStream = new FileInputStream(mergeFile);
        //源文件
        String sourceMd5Hex = DigestUtils.md5Hex(sourceFileStream);
        //合并后的文件
        String mergeMd5Hex = DigestUtils.md5Hex(mergeFileStream);
        if (sourceMd5Hex.equals(mergeMd5Hex)){
            System.out.println("合并成功");
        }

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/375084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式之ZAB协议

写在前面 假定我们现在使用zk执行了如下的指令&#xff1a; [zk: 192.168.0.10:2181(CONNECTED) 0] create /dongshidaddy 123 Created /dongshidaddy [zk: 192.168.0.10:2181(CONNECTED) 1] create /dongshidaddy/mongo 456 Created /dongshidaddy/mongo假定因为节点故障最终…

Python曲线肘部点检测-膝部点自动检测

文章目录一. 术语解释二. 拐点检测肘部法则是经常使用的法则。很多时候&#xff0c;可以凭人工经验去找最优拐点&#xff0c;但有时需要自动寻找拐点。最近解决了一下这个问题&#xff0c;希望对各位有用。一. 术语解释 **肘形曲线(elbow curve)**类似人胳膊状的曲线&#xff…

Echarts 每个柱子一种渐变色的象形柱状图

第023个点击查看专栏目录本示例是解决每个柱状图的每一个柱子都呈现一种渐变色&#xff0c;每个柱子的颜色都不同。这里同时采用了象形的柱状图效果。 文章目录示例效果示例源代码&#xff08;共125行&#xff09;相关资料参考专栏介绍示例效果 示例源代码&#xff08;共125行&…

JavaScript DOM【快速掌握知识点】

目录 DOM简介 获取元素 修改元素 添加和移除元素 事件处理 DOM简介 JavaScript DOM 是指 JavaScript 中的文档对象模型&#xff08;Document Object Model&#xff09;&#xff1b;它允许 JavaScript 与 HTML 页面交互&#xff0c;使开发者可以通过编程方式动态地修改网页…

RocketMQ源码分析

RocketMQ源码深入剖析 1 RocketMQ介绍 RocketMQ 是阿里巴巴集团基于高可用分布式集群技术&#xff0c;自主研发的云正式商用的专业消息中间件&#xff0c;既可为分布式应用系统提供异步解耦和削峰填谷的能力&#xff0c;同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠…

汽轮机胀差及轴向位移(转载的)

这个文章是微信公众号推送看到的。搬运到这里方便以后学习用。 1、轴向位移和胀差的概念 轴位移指的是轴的位移量&#xff0c;而胀差则指的是轴相对于汽缸的相对膨胀量,一般轴向位移变化时其数值较小。轴向位移为正值时&#xff0c;大轴向发电机方向移&#xff0c;若此时汽缸膨…

如何快速了解一个系统?

前言 开发人员经常会面临下面一些场景&#xff1a; 新人入职&#xff0c;需要学习已有系统&#xff0c;作为 landing 的一部分&#xff0c;如何学习&#xff1f;被拉过去参与一个陌生系统的迭代开发或者系统维护&#xff08;bugfix&#xff09;&#xff0c;如何快速上手&…

关键词聚类和凸现分析-实战1——亚急性甲状腺炎的

审稿人问题第8页第26行-请指出#是什么意思&#xff0c;并解释为什么亚急性甲状腺炎在这里被列为#8。我认为在搜索亚急性甲状腺炎相关文章时&#xff0c;关键词共现分析应该提供关键词共现的数据。这些结果的实际用途是什么?亚急性甲状腺炎是一种较为罕见但重要的甲状腺疾病&am…

vue + qiankun 项目搭建

一、cli3构建vue2项目 1、前期工作&#xff1a;查看cli安装情况与安装 npm install -g vue/cli 已安装情况查看&#xff1a;vue -V(大写的V) 2、新建项目 vue create main-project 3、选择自定义配置 配置选择 选择vue版本、babel、router、vuex、css预处理器、lint格式校…

【神经网络】GRU

1.什么是GRU GRU&#xff08;Gate Recurrent Unit&#xff09;门控循环单元&#xff0c;是循环神经网络&#xff08;RNN&#xff09;的变种种&#xff0c;与LSTM类似通过门控单元解决RNN中不能长期记忆和反向传播中的梯度等问题。与LSTM相比&#xff0c;GRU内部的网络架构较为简…

Android 实现菜单拖拽排序

效果图简介本文主角是ItemTouchHelper。它是RecyclerView对于item交互处理的一个「辅助类」&#xff0c;主要用于拖拽以及滑动处理。以接口实现的方式&#xff0c;达到配置简单、逻辑解耦、职责分明的效果&#xff0c;并且支持所有的布局方式。功能拆解功能实现4.1、实现接口自…

【员工管理系统】

员工管理系统前言需求分析系统设计系统框图所需技术系统实现编写代码测试前言 这是一个使用epoll实现TCP并发服务器&#xff0c;并让客户端登录服务器可以进行员工的管理&#xff0c;员工的信息存储在sqlite数据库中&#xff0c;对数据库进行增删改查实现对员工的添加&#xf…

一文理解服务端渲染SSR的原理,附实战基于vite和webpack打造React和Vue的SSR开发环境

SSR和CSR 首先&#xff0c;我们先要了解什么是SSR和CSR&#xff0c;SSR是服务端渲染&#xff0c;CSR是客户端渲染&#xff0c;服务端渲染是指 HTTP 服务器直接根据用户的请求&#xff0c;获取数据&#xff0c;生成完整的 HTML 页面返回给客户端&#xff08;浏览器&#xff09;展…

嵌入式 STM32 通讯协议--MODBUS

目录 一、自定义通信协议 1、协议介绍 2、网络协议 3、自定义的通信协议 二、MODBUS通信协议 1、概述 2、MODBUS帧结构 协议描述 3、MODBUS数据模型 4、MODBUS事务处理的定义 5、MODBUS功能码 6、功能码定义 7、MODBUS数据链路层 8、MODBUS地址规则 9、MO…

SpringBoot 2.x ——使用 mail 实现邮件发送

文章目录前言环境、版本等pom依赖引入springboot项目配置文件获取邮箱授权码配置properties文件定义接口信息接收类编写邮件发送服务类编写接口swagger测试1、简单邮件发送2、html格式发送(支持附件)前言 最近再看xxl-job的源码&#xff0c;其中在邮件告警通知中使用到了告警信…

Go调用dll 解决方案 dll查看工具

准备工作 Go需要1.10版本&#xff0c;即支持动态链接库 基本调用代码 lib : syscall.NewLazyDLL("lib/plugin.dll") // 读取dll f : lib.NewProc("Sum") // 调用dll函数 res, _, _ : f.Call(param) // 传值 fmt.Println(res)可能出现的问题 %1 is not a …

移动硬盘不显示怎么办?恢复硬盘的方法汇总

在日常工作和生活中&#xff0c;移动硬盘是非常重要的存储设备&#xff0c;它们可以储存大量的数据&#xff0c;比如照片、音乐、视频、文档等。但是&#xff0c;有时候你可能会遇到移动硬盘不显示的问题。这个问题通常会让人感到困惑&#xff0c;因为你无法访问移动硬盘里的数…

Appium自动化测试之启动时跳过初始化设置

Appium每次启动时都会检查和安装Appium Settings&#xff0c;这是完全没有必要的&#xff0c;在首次使用Appium连接设备是Appium Settings便已经安装好。怎样跳过安装Appium Settings呢&#xff1f;之前的做法是修改appium中的源文件中的android-helpers.js实现&#xff0c;如M…

足球俱乐部管理系统

技术&#xff1a;Java、JSP等摘要&#xff1a;网站是一种主要的渠道。人们通过互联网快速、准确的发布信息、获取信息。而足球俱乐部是足球职业化、专业化的一个标志&#xff0c;是足球运动员以足球谋生时&#xff0c;所被聘用的机构&#xff0c;应运时代发展&#xff0c;规模、…

观测云产品更新|新增用户访问监测自动化追踪;新增 CDN 质量分析;新增自定义查看器导航菜单等

观测云更新 用户访问监测优化 新增用户访问监测自动化追踪 用户访问监测新增自动化追踪&#xff0c;通过“浏览器插件”的实现方式&#xff0c;使用浏览器记录用户访问行为&#xff0c;创建无代码的端到端测试。更多详情可参考文档【 自动化追踪 】https://docs.guance.com/…