大文件分片上传的实现【前后台完整版】
在一般的产品开发过程中,大家多少会遇到上传视频功能的需求,往往我们采用的都是对视频大小进行限制等方法,来防止上传请求超时,导致上传失败。这时候可能将视频分片上传可以对你的项目有一个小小的体验优化。
本片文章前端是vue,后台基于PHP进行的分片上传,需要的小伙伴可以借鉴。
分片上传
1、什么是分片上传
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为Part)来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。
2、分片上传的场景
(1)大文件上传
(2)网络环境环境不好,存在需要重传风险的场景
3、实现流程步骤
a、方案一,常规步骤、本文实现的步骤
将需要上传的文件按照一定的分割规则,分割成相同大小的数据块;
初始化一个分片上传任务,返回本次分片上传唯一标识;
按照一定的策略(串行或并行)发送各个分片数据块;
发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件。
b、方案二
前端(客户端)需要根据固定大小对文件进行分片,请求后端(服务端)时要带上分片序号和大小
服务端创建conf文件用来记录分块位置,conf文件长度为总分片数,每上传一个分块即向conf文件中写入一个127,那么没上传的位置就是默认的0,已上传的就是Byte.MAX_VALUE 127(这步是实现断点续传和秒传的核心步骤)
服务器按照请求数据中给的分片序号和每片分块大小(分片大小是固定且一样的)算出开始位置,与读取到的文件片段数据,写入文件。
前端代码
template
// 上传按钮样式
移入方法
import { uploadByPieces } from "@/utils/upload"; //引入uploadByPieces方法
methods
// 分片上传
videoSaveToUrl(file) {uploadByPieces({file: file, // 获取到的视频文件pieceSize: 3, // 分片大小 这里是3M一片success: (data) => {this.formValidate.video_link = data.file_path;this.progress = 100; // 上传成功 进度条为100%},error: (e) => {this.$Message.error(e.msg); //报错信息},uploading: (chunk, allChunk) => {this.videoIng = true; // 上传时进度条展示 根据需要添加let st = Math.floor((chunk / allChunk) * 100); 这里是用上传的第几片除以总片数进行百分比计算this.progress = st;},});return false;
},
utils/upload
utils/upload
import md5 from 'js-md5' //引入MD5加密
import { upload } from '@/api/upload.js' // 这里指前端调用接口的api方法
export const uploadByPieces = ({ file, pieceSize = 2, success, error, uploading }) => {// 如果文件传入为空直接 return 返回if (!file) returnlet fileMD5 = ''// 总文件列表const chunkSize = pieceSize * 1024 * 1024 // 5MB一片const chunkCount = Math.ceil(file.size / chunkSize) // 总片数console.log(chunkSize, chunkCount)// 获取md5const readFileMD5 = () => {// 读取视频文件的md5console.log("获取文件的MD5值")let fileRederInstance = new FileReader()console.log('file', file)fileRederInstance.readAsBinaryString(file)fileRederInstance.addEventListener('load', e => {let fileBolb = e.target.resultfileMD5 = md5(fileBolb)console.log('fileMD5', fileMD5)console.log("文件未被上传,将分片上传")readChunkMD5()})}const getChunkInfo = (file, currentChunk, chunkSize) => {let start = currentChunk * chunkSizelet end = Math.min(file.size, start + chunkSize)let chunk = file.slice(start, end)return { start, end, chunk }}// 针对每个文件进行chunk处理const readChunkMD5 = async () => {// 针对单个文件进行chunk上传for (var i = 0; i < chunkCount; i++) {const { chunk } = getChunkInfo(file, i, chunkSize)console.log("总片数" + chunkCount)console.log("分片后的数据---测试:" + i)await uploadChunk({ chunk, currentChunk: i, chunkCount })}}const uploadChunk = (chunkInfo) => {// progressFun()return new Promise((resolver, reject) => {let config = {headers: {'Content-Type': 'multipart/form-data'}}// 创建formData对象,下面是结合不同项目给后端传入的对象。let fetchForm = new FormData()fetchForm.append('chunkNumber', chunkInfo.currentChunk + 1) // 第几片fetchForm.append('chunkSize', chunkSize) // 分片大小的限制 例如限制 5MfetchForm.append('currentChunkSize', chunkInfo.chunk.size) // 每一片的大小fetchForm.append('file', chunkInfo.chunk) //每一片的文件fetchForm.append('filename', file.name) // 文件名 fetchForm.append('totalChunks', chunkInfo.chunkCount) //总片数fetchForm.append('md5', fileMD5)upload(fetchForm, config).then(res => {console.log("分片上传返回信息:", res)if (res.data.code == 1) {// // 结合不同项目 将成功的信息返回出去// 下面如果在项目中没有用到可以不用打开注释uploading(chunkInfo.currentChunk + 1, chunkInfo.chunkCount)resolver(true)} else if (res.data.code == 2) {if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {console.log("分片上传成功")} else {// 当总数大于等于分片个数的时候if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {console.log("文件开始------合并成功")success(res.data)}}}}).catch((e) => {error && error(e)})})}readFileMD5() // 开始执行代码
}
后端代码
控制器
/*** 视频分片上传* @return mixed*/public function videoUpload(){$data = $this->request->postMore([['chunkNumber', 0],//第几分片['currentChunkSize', 0],//分片大小['chunkSize', 0],//总大小['totalChunks', 0],//分片总数['file', 'file'],//文件['md5', ''],//MD5['filename', ''],//文件名称]);$res = $this->service->videoUpload($data, $_FILES['file']);return app('json')->success($res);}
方法
/*** 视频分片上传* @param $data* @param $file* @return mixed*/public function videoUpload($data, $file){$public_dir = app()->getRootPath() . 'public';$dir = '/uploads/attach/' . date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d');$all_dir = $public_dir . $dir;if (!is_dir($all_dir)) mkdir($all_dir, 0777, true);$filename = $all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber'];move_uploaded_file($file['tmp_name'], $filename);$res['code'] = 0;$res['msg'] = 'error';$res['file_path'] = '';if ($data['chunkNumber'] == $data['totalChunks']) {$blob = '';for ($i = 1; $i <= $data['totalChunks']; $i++) {$blob .= file_get_contents($all_dir . '/' . $data['filename'] . '__' . $i);}file_put_contents($all_dir . '/' . $data['filename'], $blob);for ($i = 1; $i <= $data['totalChunks']; $i++) {@unlink($all_dir . '/' . $data['filename'] . '__' . $i);}if (file_exists($all_dir . '/' . $data['filename'])) {$res['code'] = 2;$res['msg'] = 'success';$res['file_path'] = $dir . '/' . $data['filename'];}} else {if (file_exists($all_dir . '/' . $data['filename'] . '__' . $data['chunkNumber'])) {$res['code'] = 1;$res['msg'] = 'waiting';$res['file_path'] = '';}}return $res;}
在实现分片上传的过程,需要前端和后端配合,比如前后端的上传块号的文件大小,前后端必须得要一致,否则上传就会有问题。其次文件相关操作正常都是要搭建一个文件服务器的,比如使用fastdfs、hdfs等。
本示例代码在电脑配置为4核内存8G情况下,上传24G大小的文件,上传时间需要30多分钟,主要时间耗费在前端的md5值计算,后端写入的速度还是比较快。
如果项目组觉得自建文件服务器太花费时间,且项目的需求仅仅只是上传下载,那么推荐使用阿里的oss服务器,其介绍可以查看官网:
https://help.aliyun.com/product/31815.html
阿里的oss它本质是一个对象存储服务器,而非文件服务器,因此如果有涉及到大量删除或者修改文件的需求,oss可能就不是一个好的选择。
以上就是视频分片上传的前后台的所有代码,其中有需求小伙伴可以自行加入视频上传验证,断点续传等操作。
相关文章:

大文件分片上传的实现【前后台完整版】
在一般的产品开发过程中,大家多少会遇到上传视频功能的需求,往往我们采用的都是对视频大小进行限制等方法,来防止上传请求超时,导致上传失败。这时候可能将视频分片上传可以对你的项目有一个小小的体验优化。 本片文章前端是vue&…...

Java序列化面试总结
Java序列化与反序列化是什么? Java序列化是指把Java对象转换为字节流的过程,而Java反序列化是指把字节流恢复为Java对象的过程。 序列化: 序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。核心作用是对象…...

fs的常用方法
以下是fs模块的一些常用方法: 1. 读取文件内容 使用fs.readFile()方法读取文件内容。该方法接收两个参数:文件路径和回调函数。回调函数的参数包括错误信息和文件内容。 javascript const fs require(fs); fs.readFile(/path/to/file, (err, data)…...

【华为OD机试 2023最新 】字符串重新排列、字符串重新排序(C++ 100%)
文章目录 题目描述输入描述输出描述用例题目解析C++题目描述 给定一个字符串s,s包括以空格分隔的若干个单词,请对s进行如下处理后输出: 1、单词内部调整:对每个单词字母重新按字典序排序 2、单词间顺序调整: 1)统计每个单词出现的次数,并按次数降序排列 2)次数相同,按…...

Matlab自动消除论文插图白边的7种方法
通过Matlab所绘制的插图,如不进行一定的调整,其四周往往存在一定范围的白边。 白边的存在会影响数据展示效果,有时也会给论文的排版造成一定麻烦。 要想消除白边,一种简单的方法是,在导出插图后,用其它软…...

Python每日一练(20230330)
目录 1. 存在重复元素 🌟 2. 矩阵置零 🌟🌟 3. 回文对 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1…...

面试官:Tomcat 在 SpringBoot 中是如何启动的(二)
文章目录 总结彩蛋我们再看看Tomcat类的源码: //部分源码,其余部分省略。 public class Tomcat {//设置连接器public void setConnector(Connector connector) {Service service = getService(...

软件测试岗位中,如何顺利拿下50K+?送你一份涨薪秘籍
随着科技发展以及5G时代的到来,IT行业早已发生翻天覆地的变化。已不是当初你认为只要有好点子就能立马起盘做项目的时代了。在IT行业高速发展的时期中“软件测试行业”仍然是热门行业之一。软件行业的高速发展必然带来更多的岗位,正如IT行业发展需要有开…...

java webflux函数式实现数据结构
我前面写的文章 java webflux注解方式写一个可供web端访问的数据接口 带大家写了个注解方式实现的webflux 首先 使用函数式时 您需要自己初始化服务器 使用函数式需要两个接口 分别是 RouterFunction 和 HandlerFuncion RouterFunction主要的作用就是分别一下任务 例如 添加 直…...

百度文心一言可以完胜ChatGPT的4点可能性
文心一言,百度全新一代知识增强大语言模型,文心大模型家族的新成员,能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。但说实话,很多人拿他与ChatGPT相对比&#x…...

大型分布式架构设计
大型网站的特点 大型网站架构技术 大型网站架构技术-架构模式 大型网站架构技术-高性能架构 以用户为中心,提供快速的访问体验。主要体现在:响应快、并发能力高和性能稳定。 大型网站架构技术-高可用架构 大型网站在任何时候都应该可以正常访问&#…...

基于springboot实现校园在线拍卖电商系统【源码】
基于springboot实现校园在线拍卖系统演示开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包&…...

SaaS智慧校园源码,电子班牌管理系统 人脸考勤、综合评价系统、请假管理、校务管理
Java智慧校园系统源码 智慧学校源码 小程序电子班牌,前后端分离架构 智慧校园全套源码包含:电子班牌管理系统、成绩管理系统、考勤人脸刷卡管理系统、综合素养评价系统、请假管理系统、电子班牌发布系统、校务管理系统、小程序移动端、教师后台管理系统…...

MONGODB mongodb 一般人不知道的数据类型与使用
开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…...

蚁群算法优化
%%%%%%%%%%%%蚁群算法解决 TSP 问题%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%% clear all; %清除所有变量 close all; %清图 clc; %清屏 m 50; %蚂蚁个数 Alpha 1; %信息素重要程度参数 Beta 5; %启发式因子重要程度参数 Rho 0.1; %信息素蒸发系数 G 20…...

山东首版次申报的材料
首版次软件基本知识: 1、 首版次高端软件的定义: 首版次高端软件是指省内企事业单位通过自主开发或者合作开发其功能或性能有重大突破 在该领域具有技术领先优势或者打破市场垄断拥有自主知识产权 尚未取得重大市场业绩的 同产品名称、同一版本号的软件产品。 2、主管部门:山…...

个人时间管理网站—首页的前端实现【源码】
🌟所属专栏:献给榕榕 🐔作者简介:rchjr——五带信管菜只因一枚 😮前言:该专栏系为女友准备的,里面会不定时发一些讨好她的技术作品,感兴趣的小伙伴可以关注一下~👉文章简…...

Python毕业设计推荐
今天给大家推荐4个基于python的毕业设计/课程设计 1 网上商城系统 这是一个基于pythonvue开发的商城网站,平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能…...

使用nodemon时报错:“无法加载文件...,因为在此系统上禁止运行脚本“;windows执行策略修改
报错内容如下图: Windows 系统会对全局安装的脚本进行一个限制,防止恶意脚本执行,所以此处会报错。 如何解决?通过修改 windows 执行策略来解决此问题。 一、什么是 windows 执行策略 Windows 给 PowerShell 设定了一个叫 “…...

网络协议分析期末复习(五)
目录 0.前言 1.PC和PPPOE服务器建立连接的流程以及包含LCP配置选项的PPP帧 -Discovery阶段 -Session阶段 -Terminate阶段 包含LCP配置选项的PPP帧如下 2.ARP的步骤以及过程中的具体ARP报文 Step1:查看路由表项以及本地的ARP缓存表 Step2:发送ARP…...

外贸找客户软件:Yellow Page Spider 8.7.1 Crack
黄页蜘蛛 |黄页提取器 从PAGINE GIALLE中提取数据,电子邮件,公司,协会,商业活动的电话! Yellow Page Spider 8.7.1对于那些在附近或任何意大利地点寻找商业活动、公司、协会、各种俱乐部的人来说,PagineGia…...

博客管理系统(前端页面设计)
文章目录一、预期效果二、博客列表页三、博客详情页四、博客登录页五、博客编辑页一、预期效果 博客登录页: 博客列表页: 博客详情页: 博客编辑页: 目录结构: 大家需要注意,我们下述代码的所有路径都…...

安装yolov5环境
当今世界上,深度学习技术在各个领域都有广泛的应用,因此掌握深度学习技术对于从事人工智能相关工作的人来说是非常重要的。而 YOLOv5 是一个非常流行的目标检测框架,本文将介绍如何在 Ubuntu 系统上安装 YOLOv5 环境。 1.安装 Anaconda Ana…...

IP 归属地查询 API 教你从0到1顺着网线找到键盘侠
写在前面 前一段时间,微博、头条、抖音、知乎等各大互联网平台相继推出了“个人主页、评论显示 IP 属地,用户不能自己开启或关闭”的功能,那么这些平台是如何获取到用户的 IP 地址呢? 本文将从 IP 归属地的技术原理、实际应用场…...

【K8S系列】深入解析Pod对象(二)
目录 序言 1.Volume 简单介绍 2 Projected Volume 介绍 2.1 Secret 2.1.1 yaml讲解 2.1.2 创建Pod 2.2 Downward API 2.2.1 yaml示例 2.2.2 Downward API 支持字段 3 投票 序言 任何一件事情,只要坚持六个月以上,你都可以看到质的飞跃。 在…...

从3千到3万,我的测试之路真的坎坷
其实测试行业未来发展之路是几乎所有关于软件测试工程师都会在意的话题,相信各位看官也很迷茫自己的发展路线。为了方便大家选择和比较,我也将我的经验和观点分享出来,以作参考。如果小伙伴们有更好的观点,欢迎分享和探讨…...

linux下使用system函数在程序中运行linux的shell命令
一、功能 linux下在程序中调用shell命令实现某个功能,比如拷贝命令cp 二、使用 添加头文件 #include <stdlib.h> 函数原型 int system(const char *command); 描述说明是system的调用过程: 使用fork创建一个子进程,子进程使用 execl 执…...

银行数字化转型导师坚鹏:银行业发展趋势及对人才的需求分析
数字化转型背景下银行业发展趋势及对人才的需求分析 ——洞察先机,重塑人才核心竞争力 课程背景: 数字化转型背景下,很多银行存在以下问题:不知道银行整体发展现状与发展趋势?不清楚金融科技对银行发展有什么影响&…...

NFS挂载
0、创建 mkdir /nfsdata mkfs.xfs /dev/vdb mount /dev/vdb /nfsdata 1、两边主机启动nfs服务 service nfs start 2、被挂载主机查看,文件系统是否可挂载 showmount -e 3、将被挂载主机,设置任何主机可挂载文件系统 vi /etc/exports /nfsdata (in…...

IDEA使用技巧
IntelliJ IDEA是一款流行的Java集成开发环境(IDE),它为开发者提供了许多有用的功能和工具来提高他们的工作效率和开发质量。直接使用IntelliJ IDEA就相当于节省了自己的时间,如果先使用其他编译器后来在使用IntelliJ IDEA会觉得非…...