28-大文件上传(了解)

news2024/11/22 21:13:19

一、是什么?

🚗🚗🚗不管怎样简单的需求,在量级达到一定层次时,都会变得异常复杂。
文件上传简单,文件变大就复杂
上传时,以下几个注意点会影响用户体验

  • 服务器处理数据的能力
  • 请求超时
  • 网络波动
    上传时间会变长,高频次文件上传失败,失败后又需要重新上传等等
    为了解决上述问题,我们需要对大文件上传单独处理
    分片上传断点续传两个概念

二、分片上传

🚓🚓
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(Part)来进行分片上传
在这里插入图片描述

上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件

大致流程如下:
1,将需要上传的文件按照一定的分割规则,分割成相同大小的数据块;
2.初始化一个分片上传任务,返回本次分片上传唯一标识;
3,按照一定的策略(串行或并行)发送各个分片数据块;
4,发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件

断点续传

🚕🚕
断点续传指的是在下载上传时,将下载或上传任务人为的划分为几个部分

每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。用户可以节省时间,提高速度
一般实现方式有两种:

  • 服务器端返回,告知从哪开始
  • 浏览器端自行处理

上传过程中将文件在服务器写为临时文件,等全部写完了(文件上传完),将此临时文件重命名为正式文件即可;

如果中途上传中断过,下次上传的时候根据当前临时文件大小,作为在客户端读取文件的偏移量,从此位置继续读取文件数据块,上传到服务器从此偏移量继续写入文件即可

二、实现思路

整体思路,拿到文件,保存文件唯一标识,切割文件,分段上传,每次上传一段,根据唯一标识判断文件上传进度,直到文件的全部片段上传完毕

在这里插入图片描述
下面的内容都是伪代码

读取文件内容:

const input = document.querySelector('input');
input.addEventListener('change', function() {
    var file = this.files[0];
});

可以使用md5实现文件的唯一

const md5code = md5(file);

然后开始对文件进行分割

var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.addEventListener("load", function(e) {
    //每10M切割一段,这里只做一个切割演示,实际切割需要循环切割,
    var slice = e.target.result.slice(0, 10*1024*1024);
});

h5上传一个(一片)

const formdata = new FormData();
formdata.append('0', slice);
//这里是有一个坑的,部分设备无法获取文件名称,和文件类型,这个在最后给出解决方案
formdata.append('filename', file.filename);
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function() {
    //xhr.responseText
});
xhr.open('POST', '');
xhr.send(formdata);
xhr.addEventListener('progress', updateProgress);
xhr.upload.addEventListener('progress', updateProgress);

function updateProgress(event) {
    if (event.lengthComputable) {
        //进度条
    }
}

这里给出常见的图片和视频的文件类型判断

function checkFileType(type, file, back) {
/**
* type png jpg mp4 ...
* file input.change=> this.files[0]
* back callback(boolean)
*/
    var args = arguments;
    if (args.length != 3) {
        back(0);
    }
    var type = args[0]; // type = '(png|jpg)' , 'png'
    var file = args[1];
    var back = typeof args[2] == 'function' ? args[2] : function() {};
    if (file.type == '') {
        // 如果系统无法获取文件类型,则读取二进制流,对二进制进行解析文件类型
        var imgType = [
            'ff d8 ff', //jpg
            '89 50 4e', //png

            '0 0 0 14 66 74 79 70 69 73 6F 6D', //mp4
            '0 0 0 18 66 74 79 70 33 67 70 35', //mp4
            '0 0 0 0 66 74 79 70 33 67 70 35', //mp4
            '0 0 0 0 66 74 79 70 4D 53 4E 56', //mp4
            '0 0 0 0 66 74 79 70 69 73 6F 6D', //mp4

            '0 0 0 18 66 74 79 70 6D 70 34 32', //m4v
            '0 0 0 0 66 74 79 70 6D 70 34 32', //m4v

            '0 0 0 14 66 74 79 70 71 74 20 20', //mov
            '0 0 0 0 66 74 79 70 71 74 20 20', //mov
            '0 0 0 0 6D 6F 6F 76', //mov

            '4F 67 67 53 0 02', //ogg
            '1A 45 DF A3', //ogg

            '52 49 46 46 x x x x 41 56 49 20', //avi (RIFF fileSize fileType LIST)(52 49 46 46,DC 6C 57 09,41 56 49 20,4C 49 53 54)
        ];
        var typeName = [
            'jpg',
            'png',
            'mp4',
            'mp4',
            'mp4',
            'mp4',
            'mp4',
            'm4v',
            'm4v',
            'mov',
            'mov',
            'mov',
            'ogg',
            'ogg',
            'avi',
        ];
        var sliceSize = /png|jpg|jpeg/.test(type) ? 3 : 12;
        var reader = new FileReader();
        reader.readAsArrayBuffer(file);
        reader.addEventListener("load", function(e) {
            var slice = e.target.result.slice(0, sliceSize);
            reader = null;
            if (slice && slice.byteLength == sliceSize) {
                var view = new Uint8Array(slice);
                var arr = [];
                view.forEach(function(v) {
                    arr.push(v.toString(16));
                });
                view = null;
                var idx = arr.join(' ').indexOf(imgType);
                if (idx > -1) {
                    back(typeName[idx]);
                } else {
                    arr = arr.map(function(v) {
                        if (i > 3 && i < 8) {
                            return 'x';
                        }
                        return v;
                    });
                    var idx = arr.join(' ').indexOf(imgType);
                    if (idx > -1) {
                        back(typeName[idx]);
                    } else {
                        back(false);
                    }

                }
            } else {
                back(false);
            }

        });
    } else {
        var type = file.name.match(/\.(\w+)$/)[1];
        back(type);
    }
}

调用

checkFileType('(mov|mp4|avi)',file,function(fileType){
    // fileType = mp4,
    // 如果file的类型不在枚举之列,则返回false
});

上面上传文件的一步,可以改成

formdata.append('filename', md5code+'.'+fileType);

有了切割上传后,也就有了文件唯一标识信息,断点续传变成了后台的一个小小的逻辑判断

后端主要做的内容为:根据前端传给后台的md5值,到服务器磁盘查找是否有之前未完成的文件合并信息(也就是未完成的半成品文件切片),取到之后根据上传切片的数量,返回数据告诉前端开始从第几节上传

如果想要暂停切片的上传,可以使用XMLHttpRequest的 abort方法

使用场景

  • 大文件加速上传:当文件大小超过预期大小时,使用分片上传可实现并行上传多个 部分, 以加快上传速度
  • 网络环境较差:建议使用分片上传。当出现上传失败的时候,仅需重传失败的部分
  • 流式上传:可以在需要上传的文件大小还不确定的情况下开始上传。这种场景在视频监控等行业应用中比较常见

小结

考虑到更多场景

  • 切片上传失败怎么办
  • 上传过程中刷新页面怎么办
  • 如何进行并行上传
  • 切片什么时候按数量切,什么时候按大小切
  • 如何结合 Web Worker 处理大文件上传
  • 如何实现秒传

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

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

相关文章

AI PPT 一句话搞定PPT讲演搞

相信大家在职场中&#xff0c;一定会接触过写PPT&#xff0c;经常会把你搞得焦头烂额。在大部分的公司里&#xff0c;写PPT汇报又是不可能逃避的事情。但随着AI时代的到来&#xff0c;有很多AI帮你写PPT的工具也逐渐崭露头角&#xff0c;可以自动帮助你制作出华丽的PPT&#xf…

HOT47-从前序与中序遍历序列构造二叉树

leetcode原题链接&#xff1a;从前序与中序遍历序列构造二叉树 题目描述 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder …

攻防演练中红队常用的攻击方法之横向移动(上)

横向移动&#xff0c;是攻击者侵入企业系统时&#xff0c;获取相关权限及重要数据的常见攻击手法。了解横向移动的原理有助于个人和企业更好地维护网络安全。 中安网星特此推出了横向移动科普系列&#xff0c;本系列共有三篇文章。 近年来&#xff0c;随着网络攻击、勒索事件…

B. Number Factorization - 数论

分析&#xff1a; 可以将n分解成质因数&#xff0c;要求是加和尽可能大&#xff0c;那么可以让所有的指数都是1&#xff0c;a*b>ab一定成立&#xff0c;所以要尽可能地将质因数乘在一起组成更大的数&#xff0c;加在一起得到最后的解。 代码&#xff1a; #include <bit…

Matlab中解常微分方程(组)的命令

常微分方程组求解命令与示例 线性常微分方程&#xff08;组&#xff09; ode45 4 order 龙格库塔法example odefun (t, y) [-2*y(1) y(2); y(1) - 2*y(2)]; tspan [0 10]; y0 [1; 0]; [t, y] ode45(odefun, tspan, y0); ode23 使用二三阶Bogacki-Shampine方法求解非刚性…

Devops系列二(使用helm chart,将java应用发布部署至k8s的示例)

一、接着上一篇的话 docker镜像已经有了&#xff0c;本文我们将接着演示如何使用helm部署应用到k8s。 分为两大部分&#xff1a; 制作helm chart&#xff0c;推送到私有仓库nexushelm拉取chart&#xff0c;部署到k8s 二、制作helm chart 要求你先安装helm&#xff0c;随便一…

Rust 第四天—Rust进阶1

上一篇介绍了Rust的所有权特性,今天就把剩下一些之前没介绍但项目中常用的内容总结一下. 结构体泛型trait 1 结构体 和c语言一样,Rust使用struct关键字来定义一个结构体,结构体可以将不同的类型数据进行整合,加快内存访问速度. 1.1 结构体定义 struct Test{username:Strin…

【第四天学习】决策分支,判断语录

决策分支 If语句 If语句是对基础的一种选择结构语句&#xff0c;它主要有三种形式&#xff0c;分别是if语句&#xff0c;if else语句和if else If else多分支语句。 int nCheck 0; if(nNum4) { nCheck4; } else { nCheck8; }If语句其实就是一个判断语句&#xff0c;它会判断…

详细解释lvs的工作原理

vsl用于集群中的直接路由它的原理如下 如果在公司并发太高了怎么解决 1.加配置cpu 内存 带宽 ssd高效硬盘 2.加服务器 为用户提供服务 横向扩展 集群是什么 由的多台主机构成,相当于一台大型计算机,只提供一个访问入口(域名与ip地址) 集群用在那个场景 高并发场景 vrrp是…

linux下删除ARP缓存表【网络工程】(保姆级图文)

目录 linux下删除ARP缓存表总结 欢迎关注 『网络工程专业』 系列&#xff0c;持续更新中 欢迎关注 『网络工程专业』 系列&#xff0c;持续更新中 温馨提示&#xff1a;对虚拟机做任何设置&#xff0c;建议都要先快照备份&#xff01; linux下删除ARP缓存表 这里老师的命令ip…

docker的安装和使用

1.新建一个项目 比如vue init vuelatest完事之后运行打包到build目录下 2.在项目根目录下通过执行命令 touch Dockerfile 3.拉取nginx镜像 首先打开你的Docker&#xff0c;默认会启动。控制台拉取 Nginx 镜像&#xff1a;运行 docker pull nginx4.在根目录创建Nginx配置文件…

【多线程】锁策略

1. 说在前面 这里的锁策略内容&#xff0c;属于典型的面试八股文&#xff01;如果未来工作&#xff0c;需要实现一把锁&#xff0c;那么得好好研究下锁策略&#xff0c;但基本上不会让我们自己设计一把锁的。 而这里的锁策略内容不局限于 Java&#xff0c;任何 "锁" …

python接口自动化(十七)--Json 数据处理---一次爬坑记(详解)

简介 有些 post 的请求参数是 json 格式的&#xff0c;这个前面发送post 请求里面提到过&#xff0c;需要导入 json模块处理。现在企业公司一般常见的接口因为json数据容易处理&#xff0c;所以绝大多数返回数据也是 json 格式的&#xff0c;我们在做判断时候&#xff0c;往往只…

golang 实现四层负载均衡

大家好&#xff0c;我是蓝胖子&#xff0c;做开发的同学应该经常听到过负载均衡的概念&#xff0c;今天我们就来实现一个乞丐版的四层负载均衡&#xff0c;并用它对mysql进行负载均衡测试&#xff0c;通过本篇你可以了解到零拷贝的应用&#xff0c;四层负载均衡的本质以及实践。…

代码模版-element plus如何进行前端校验输入框

文章目录 步骤一&#xff1a;引入 element plus 框架步骤二&#xff1a;使用 element plus 的 form步骤三&#xff1a;form 明确指定 rules步骤四&#xff1a;事件触发校验 使用 vue3 element plus 步骤一&#xff1a;引入 element plus 框架 先 npm 安装 在 src/main.js 中…

linux[armbian]环境安装nginx

文章目录 linux[armbian]环境安装常用命令遇到的问题和解决方法问题一&#xff1a;conf/koi-win复制错误解决方法问题二&#xff1a;缺少相关的日志目录解决方法 linux[armbian]环境安装 下载Nginx&#xff1a; 访问[Nginx官方网站]&#xff08;https://nginx.org/)&#xff0c…

排序算法(1):冒泡排序

在计算机科学领域&#xff0c;排序算法是一个重要的主题。冒泡排序法是最基础且简单的排序算法之一&#xff0c;它的原理简单易懂&#xff0c;是学习排序算法的理想起点。本文将详细介绍冒泡排序法的原理、实现方法以及优化技巧&#xff0c;帮助读者全面了解和掌握这一经典算法…

重新安装conda时报错

自己因为最近利用 conda 安装了比较多的软件,在输入创建环境时&#xff1a; conda create -n python27 python2.7 报错&#xff0c;环境创建不成功。 显示 miniconda3 文件夹已存在 &#xff08;因为安装时会默认安装至此目录&#xff0c;如果此目录已经存在则会冲突报错&…

【基础算法】贪心算法

贪心算法又称贪婪算法&#xff0c;是一种常见的算法思想。贪心算法的优点是效率高&#xff0c;实现较为简单&#xff0c;缺点是可能得不到最优解。 贪心算法的基本思想 贪心算法就是在求解问题时&#xff0c;总是做出当前看来最好的选择。也就是说贪心算法并不从整体最优上考…

word转PDF后图片为何会变小?怎么解决?

有些同学反映将Word文档转换为PDF后&#xff0c;发现里面的图片居然变小了&#xff0c;这是什么原因造成的&#xff1f;该怎么解决呢&#xff1f; 先来说说原因&#xff0c;我个人认为可能是由以下原因造成的&#xff1a; 1、word插入图片后压缩“太狠”了。当你在word中插入…