vue - 大文件分片上传之simple-uploader.js的使用

news2024/12/28 20:37:28

vue - 大文件分片上传之simple-uploader.js的使用

  • 分片上传的思路
  • 前端文件切片常见的写法
  • 后端常见的写法

关于大文件上传

关于单个文件上传:其实就是前端中的文件通过http传到后端后端再写入服务器的过程


那单个大文件分片上传:其实就是前端把大文件分成了好几块后端再多次写入服务器的过程

关于秒传断点续传

秒传:其实就是服务器中存在这个文件了,再次传的时候就不重新上传了,前端直接显示上传成功


断点续传:其实就是文件传了一部分,剩下的还没传。这个时候根据上传的偏移量offset,把剩下的上传到服务器

前提知识

1. 前端使用spark-md5.js对文件进行加密

   import SparkMD5 from 'spark-md5'

   const spark = new SparkMD5.ArrayBuffer()
   
   //获取文件二进制数据
   var fileReader = new FileReader()
   fileReader.readAsArrayBuffer(file) //file就是获取到的文件
   
   //异步执行函数,fileReader.readAsArrayBuffer的回调函数
   fileReader.onload = function (e) {
     spark.append(e.target.result)
     const md5 = spark.end()
     console.log(md5)  
     //打印结果这个文件会有一串唯一编码类似下面
     //4b4a94c7ff8953d7103515e91d432b0a
   }

2. simple-uploader.js的使用

                // options常见配置
                options: {
                    // 上传地址,若测试和真正上传接口不是同个路径,可以用函数模式。
                    // 如果是同一个路径,一个get请求,一个post请求
                    target: "/fileStorage/upload",
                    // 是否开启服务器分片校验。默认为 true
                    testChunks: true,
                    // 真正上传的时候使用的 HTTP 方法,默认 POST
                    uploadMethod: "post",
                    // 分片大小
                    chunkSize: CHUNK_SIZE,
                    // 并发上传数,默认为 3
                    simultaneousUploads: 3,
                    /**
                     * 检测校验是md5加密以后的事情,整个上传过程,只会执行一次。
                     * 执行一次以后,看是上传完成,还是需要继续上传
                     *
                     * 发起测试校验以后,所有分片都会进入这个回调
                     *
                     * 判断分片是否上传,秒传和断点续传基于此方法
                     * 如果后端返回的是true,代表秒传
                     * 如果后端返回[1,2,3,4,5,6,7,8,9]等(分片信息),代表可以继续上传
                     *
                     *
                     * 我个人理解的停止上传与继续上传就是断点上传
                     *
                     *
                     * 我个人理解这个方法是这样的:分块以后知道有几块了,再跟数据库做比对,知道是上传完成了,还是需要继续上传
                     * api接口只走一次检验方法,那如果是上传完成了直接ok,如果是需要继续上传,那就接着上传,组件再暴露出pause和resume方法,用于停止和继续上传。(api得到数据库数据以后,每块走这个方法,进行对比。)
                     */
                    checkChunkUploadedByResponse: (chunk, message) => {
                        console.log("message,第一次test以后,返回来的数据", chunk.offset)
                        // message是后台返回
                        let messageObj = JSON.parse(message);
                        let dataObj = messageObj.data;
                        if (dataObj.uploaded !== null) {
                            return dataObj.uploaded;
                        }
                        // 判断文件或分片是否已上传,已上传返回 true
                        // 这里的 uploadedChunks 是后台返回
                        return (dataObj.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0;
                    },
                    parseTimeRemaining: function (timeRemaining, parsedTimeRemaining) {
                        //格式化时间
                        return parsedTimeRemaining
                            .replace(/\syears?/, "年")
                            .replace(/\days?/, "天")
                            .replace(/\shours?/, "小时")
                            .replace(/\sminutes?/, "分钟")
                            .replace(/\sseconds?/, "秒");
                    },
                    // 处理所有请求的参数
                    // processParams:(params,file,chunk) => {
                    //     // 这里需要根据后端的要求,处理一些请求参数
                    //     // params.xxx = chunk.xxx // 比如一些需要在上传时,带上测试校验返回的一些信息字段
                    //     // return params;
                    // }
                },
// 常用的回调函数
    <uploader
            ref="uploader"
            :options="options"
            :autoStart="false"
            :file-status-text="fileStatusText"
            @file-added="onFileAdded"
            @file-success="onFileSuccess"
            @file-error="onFileError"
            @file-progress="onFileProgress"
            class="uploader-example"
    >

分片上传的思路

  • 先对文件进行md5加密。使用md5加密的优点是:可以对文件进行唯一标识。在后端根据md5判断文件是否存在。
  • 向后台发送第一次请求接口,且只发送一次,用于检测,接口里的数据就是我们已经上传过的文件块。用于检测是否需要秒传或者继续上传
  • 当文件存在的话,就不用重新再上传。(秒传)
  • 当文件不存在的话,且对大文件进行分片。比如一个100M的文件,我们一个分片是5M的话,那么这个文件可以分20次上传。(checkChunkUploadedByResponse方法里面判断)
  • 当文件不存在的话,且已经上传了一部分的。接着上传(checkChunkUploadedByResponse方法里面判断)
  • 向后台发送第二次请求接口,这时的请求才是正儿八经的上传请求。此时,请求可以停止和继续发。

在这里插入图片描述

前端文件切片常见的写法

// 文件切片需要是的参数:
1. var fileSize = file.size; // 文件大小
2. var CHUNK_SIZE = 2 * 1024 * 1024; // 切片的大小
3. var chunks = Math.ceil(fileSize / chunkSize); // 获取切片的个数
4. var currentChunk = 0; //  当前分片下标


// 加载下一个分片的start与end
const start = currentChunk * CHUNK_SIZE;
const end = start + CHUNK_SIZE >= file.size ? file.size : start + CHUNK_SIZE; 
			// md5 加密
            getFileMD5(file, callback) {
                // 使用SparkMD5,对文件进行加密
                let spark = new SparkMD5.ArrayBuffer();

                let fileReader = new FileReader();
                //获取文件分片对象(注意它的兼容性,在不同浏览器的写法不同)
                let blobSlice =
                    File.prototype.slice ||
                    File.prototype.mozSlice ||
                    File.prototype.webkitSlice;
                // 当前分片下标
                let currentChunk = 0;
                // 分片总数(向下取整)
                let chunks = Math.ceil(file.size / CHUNK_SIZE);
                // 暂停上传
                file.pause();

                // 第一次加载分片的方法
                loadNext();

                // fileReader.readAsArrayBuffer,读完后的回调函数
                fileReader.onload = function (e) {
                    // console.log("currentChunk :>> ", currentChunk);
                    spark.append(e.target.result);
                    if (currentChunk < chunks) {
                        currentChunk++;
                        loadNext();
                    } else {
                        // 该文件的md5值
                        let md5 = spark.end();
                        // 回调传值md5
                        callback(md5);
                    }
                };
                fileReader.onerror = function () {
                    this.$message.error("文件读取错误");
                    file.cancel();
                };

                // 加载下一个分片
                function loadNext() {
                    const start = currentChunk * CHUNK_SIZE;
                    const end =
                        start + CHUNK_SIZE >= file.size ? file.size : start + CHUNK_SIZE;
                    // 文件分片操作,读取下一分片(fileReader.readAsArrayBuffer操作会触发onload事件)
                    fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
                }

            },
			//  @file-added="onFileAdded" 回调函数
            onFileAdded(file, event) {
                console.log("onFileAdded方法执行了__flx",event)
                /*
                *  第一步,判断文件类型是否允许上传
                * */
                // todo 判断文件类型是否允许上传


                /*
                *  第二步:计算文件 MD5,并恢复上传
                * */
                this.getFileMD5(file, (md5) => {
                    console.log('MD5回调函数')
                    if (md5 !== "") {
                        // 修改文件唯一标识
                        file.uniqueIdentifier = md5;
                        // 请求后台判断是否上传
                        // 恢复上传
                        file.resume();
                    }
                });
            },

后端常见的写法

在这里插入图片描述

// 校验接口的业务逻辑
//  一共两张表,一张是每块的记录表(chunck),一张是上传完成的记录表(file)


// chunck表中的操作
// 1. 根据 identifier 查找数据是否存在
// 2. 如果查询的List的length是 0 说明文件不存在,则直接返回没有上传
// 3. 如果不是0,则拿到第一个数据,查看文件是否分片
// 4. 如果没有分片,那么直接返回已经上传成功,否则返回分片数据。
// 分片上传的逻辑
// 1. 每次上传完成以后,都把数据存到chunck表中
// 2. 当所有都上传完以后,存到文件表file中 

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

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

相关文章

SpringBoot中操作Redis解析JsonArray数据为对象List(ruoyi字典值sys_dict为例)

场景 若依前后端分离版手把手教你本地搭建环境并运行项目&#xff1a; 若依前后端分离版手把手教你本地搭建环境并运行项目_前后端分离的项目怎么跑起来_霸道流氓气质的博客-CSDN博客 在上面搭建系统的基础上&#xff0c;会将系统的字典值缓存进redis中。 看数据格式存储的是…

大数据数据湖技术Hudi0.12.0版本源码编译

0 介绍 Apache Hudi&#xff08;Hadoop Upserts Delete and Incremental&#xff09;是下一代流数据湖平台。Apache Hudi将核心仓库和数据库功能直接引入数据湖。Hudi提供了表、事务、高效的upserts/delete、高级索引、流摄取服务、数据集群/压缩优化和并发&#xff0c;同时保…

WorkPlus AI助理 | 将企业业务场景与ChatGPT结合

近年来&#xff0c;人工智能成为了企业数字化转型的热门话题&#xff0c;作为被训练的语言模型&#xff0c;ChatGPT具备模拟对话、回答问题、写代码、写小说、进行线上内容创作的能力&#xff0c;还能根据聊天的上下文进行互动。作为一款新兴的人工智能应用程序&#xff0c;对于…

jdk14至16——record关键字

record类型是从14开始预览到16成为正式版的&#xff0c;record类型是一种受限制的类&#xff0c;一般用来封装不可变对象&#xff0c;record类型会自动生成一个全部属性的构造方法&#xff0c;以及属性的get方法&#xff0c;但没有set方法&#xff0c;会自动生成hashCode()、eq…

JS中深拷贝浅拷贝的区别

深浅拷贝在MDN官方中的表述是这样的&#xff1a; 对象的深拷贝是指其属性与其拷贝的源对象的属性不共享相同的引用&#xff08;指向相同的底层值&#xff09;的副本。因此&#xff0c;当你更改源或副本时&#xff0c;可以确保不会导致其他对象也发生更改&#xff1b;也就是说&a…

vue下拉框vue字典映射转换失败 字符转数字parseInt :value vue下拉框无法选择 选什么都是最后一个 el-select默认选中 el-select设为只读 input输入框设为只读

现象&#xff1a; 解决后&#xff1a; 关键点&#xff1a; 1、value"0" 与 :value"0" 不同&#xff0c;加冒号:试试 2、:value"parseInt(dict.dictValue)" 字符串转int试试 parseInt() 写死下拉框 <el-form-item label"类型" pro…

COBOL 程序结构

COBOL 程序结构 COBOL程序结构由部&#xff08;division&#xff09;组成&#xff0c;如下图所示&#xff1a; 这些部简介如下&#xff1a; **Sections&#xff08;节&#xff09;**是程序逻辑的逻辑细分。节是段落的集合。**Paragraphs&#xff08;段&#xff09;**是一个节…

路面积水监测-路面积水监测系统

在城市化进程不断加快的背景下&#xff0c;城市道路面临着日益严重的积水问题。持续的降雨和不良的排水系统导致路面积水&#xff0c;给交通运输和城市生活带来了诸多不便和安全隐患。路面积水监测系统旨在易涝点布设内涝积水监测仪&#xff0c;实时了解路面积水情况&#xff0…

矿井水除氟,污水除氟的工艺分析

高矿化度的废水是指含有高浓度溶解性矿物质的废水&#xff0c;通常指的是含有高浓度钠、钙、镁、铁、铝、钾等离子的废水。这些离子通常来自于废水所处的环境、工业或生产过程中使用的原材料和化学品。高矿化度的废水通常具有高盐度、高电导率、高硬度等特征&#xff0c;对环境…

【Nginx】缓存集成

文章目录 缓存的概念Nginx的web缓存服务Nginx缓存设置的相关指令Nginx缓存设置案例Nginx缓存的清除方式一:删除对应的缓存目录方式二:使用第三方扩展模块 Nginx设置资源不缓存 缓存的概念 缓存就是数据交换的缓冲区(称作:Cache),当用户要获取数据的时候&#xff0c;会先从缓存…

DOUBLETROUBLE 1

文章目录 DOUBLETROUBLE: 1实战演练一、前期准备1、相关信息 二、信息收集1、nmap探测目标靶机端口2、扫描目标网址目录3、访问网站&#xff0c;发现secret下有个图片4、将图片下载5、查看图片所含内容6、破解密码并查看7、登陆邮箱8、创建反弹shell9、上传反弹shell10、监听11…

【云计算架构】通过新的优化视角查看云架构

仅仅让云部署工作不再是目标。关注构建和部署最佳解决方案的新指标和方法。 随着云计算架构的成熟&#xff0c;我们定义成功的方式也应该成熟。在2021&#xff0c;我指出&#xff0c;优化云计算更多的是二进制过程&#xff0c;而不是模拟过程。 我当时所说的仍然是正确的&#…

【医学图像】图像分割系列.1

医学图像分割是一个比较有应用意义的方向&#xff0c;本文简单介绍三篇关于医学图像分割的论文&#xff1a; UNeXt&#xff08;MICCAI2022&#xff09;&#xff0c;PHTrans&#xff08;MICCAI2022&#xff09;&#xff0c;DA-Net&#xff08;MICCAI2022&#xff09;。 目录 …

目标追踪---deepsort原理讲解

目录 一、多目标追踪的主要步骤 二、sort流程 三、Deepsort算法流程 一、多目标追踪的主要步骤 获取原始视频帧利用目标检测器对视频帧中的目标进行检测将检测到的目标的框中的特征提取出来&#xff0c;该特征包括表观特征&#xff08;方便特征对比避免ID switch&#xff0…

SQL语句练习附带答案

首先创建数据库filmclub DROP DATABASE IF EXISTS filmclub;CREATE DATABASE filmclub;USE filmclub;CREATE TABLE category (cid INT PRIMARY KEY AUTO_INCREMENT,cname VARCHAR(20) )CHARSETutf8; CREATE TABLE film (fid INT PRIMARY KEY AUTO_INCREMENT,fname VARCHAR(20)…

ChatGPT和 dalle2 配合生成故事绘本

和 dalle2 配合生成故事绘本 在之前章节中&#xff0c;我们已经尝试过让 ChatGPT 来生成一些故事情节&#xff0c;不管是影视剧还是小说还是游戏都可以。这时候&#xff0c;自然而然的可以联想到&#xff1a;那我们可不可以一步到位&#xff0c;把 ChatGPT 编出来的故事情节&a…

为什么MySQL数据库单表建议最大2KW数据?

文章目录 为什么MySQL数据库单表建议最大2KW数据&#xff1f;一、 Innodb 存储引擎1、数据存储2、数据页的结构 二、 B tree 结构三、 B 树存放数据的行数 为什么MySQL数据库单表建议最大2KW数据&#xff1f; 我们经常会听到一种说法&#xff0c;在MySQL中&#xff0c;数据库单…

Spring Security 中的 CSRF 攻击是什么?如何防止它?

Spring Security 中的 CSRF 攻击是什么&#xff1f;如何防止它&#xff1f; 什么是 CSRF 攻击&#xff1f; CSRF&#xff08;Cross-Site Request Forgery&#xff09;攻击是一种常见的网络安全威胁&#xff0c;也称为“跨站请求伪造”攻击。攻击者可以通过某些手段&#xff0…

SpringBoot整合RabbitMQ及其原理分析

上一篇&#xff1a;RabbitMQ基础知识 1、相关依赖 这里无需指定版本号&#xff0c;让其跟着SpringBoot版本走。本示例使用SpringBoot版本号为2.7.10。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-…

SaaS系统平台,如何兼顾客户的个性化需求?

在当今数字化的商业环境中&#xff0c;SaaS系统已经成为企业运营的重要组成部分之一。 SaaS系统平台的好处是显而易见的&#xff0c;可以将业务流程数字化&#xff0c;从而帮助企业提高效率并节省成本。 但是&#xff0c;由于每个企业的业务都不尽相同&#xff0c;所以在选择Sa…