Vue项目使用Websocket大文件FileReader()切片上传实例

目录
  • 使用技术
  • upfile.js文件
  • 新增需求:对上传文件流进行加密,并传给后端做验证
  • 还是在upfile.js文件(也可以单独放一个文件)

大文件上传,本地1.3G文件不到一分钟上传完毕

使用技术

  • Vue框架
  • WebSocket双向传输
  • FileReader读取文件

封装的WebSocket请求文件上传方法,目前只支持单文件上传,有研究出来多文件上传,记得评论哦

upfile.js文件

//file.slice(起始字节,终止字节)与FileReader实现文件切片读取
function PartFileReader(files, type, event) {
    this.files = files;//inputObj.files[0]
    this.type = type;  //配置FileReader读取文件的方法
    this.event = event;//配置读取文件时需要触发的事件
    this.total = files.size;//获取文件大小
    this.step = 1024 * 1024 * 10;//1MB(单片大小/一兆)
    this.loaded = 0; //文件当前读取进度
    this.reader = new FileReader(); //实际读取文件的FileReader对象实例
    this.abort = this.reader.abort; //中断文件读取(可以通过中断文件读取事件保留切片数据,实现下一次可以在原读取位置继续开始读取)
    this.readPartFile(this.loaded); //开启读取文件
    this.bindEvent();//绑定FileReader文件读取
}
//给切片读取对象原型上添加FileReader获取读取类型,开启读取文件
PartFileReader.prototype.readPartFile = function (start) {
    if (this.files.slice) {
        var file = this.files.slice(start, this.loaded + this.step);
        switch (this.type) {
        // 开始读取指定的 Blob中的内容,根据读取方式不同,result最后返回的数据也不同
            case 'readAsBinaryString' :	// result属性中将包含所读取文件的原始二进制数据。
                this.reader.readAsBinaryString(file);
                break;
            case 'readAsDataURL' :	// result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容。
                this.reader.readAsDataURL(file);
                break;
            case 'readAsArrayBuffer' :	// result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象。
                this.reader.readAsArrayBuffer(file);
                break;
            case 'readAsText' : // 一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。
                this.readAsText(file);
                break;
        }
    }
}
//给切片读取对象原型上绑定FileReader对象事件
PartFileReader.prototype.bindEvent = function () {
    var self = this;
    this.reader.onloadstart = function (e) {    // FileReader.onloadstart 该事件在读取操作开始时触发。
        self.event.loadStart && self.event.loadStart.call(this, e);
    }
    this.reader.onprogress = function (e) { // FileReader.onprogress 该事件在读取Blob时触发。
        self.event.progress && self.event.progress.call(this, e);
    }
    this.reader.onload = function (e) { // FileReader.onload 该事件在读取操作完成时触发。
        // 切片读取文件有别于非切片读取,切片读取的文件读取状态需要在每个切片读取成功后再刷新读取进度
        self.loaded += e.loaded;
        self.event.load && self.event.load.call(this, e, self.loaded, self.total);
        if (self.loaded < self.total) {
            self.readPartFile(self.loaded);
        }
    }
    this.reader.onloadend = function (e) {  // FileReader.onloadend 该事件在读取操作结束时(要么成功,要么失败)触发。
        self.event.loadend && self.event.loadend.call(this, e);
    }
    this.reader.onabort = function (e) {   // FileReader.onabort 该事件在读取操作被中断时触发。
        self.event.abort && self.event.abort.call(this, e);
    }
}
function readFile(socket,file,obj) {
    console.log("文件",file);
    var reader = new PartFileReader(file, 'readAsArrayBuffer', {
        loadStart: function (e) {
           // progressTextObj.innerText = "正在读取文件(0%)...";
        },
        progress: function (e) {
        },
        load: function (e, loaded, total) {
            // 如果在读取的基础上写上传的话在这里获取读取成功的文件切片
            // e.target.result //当前文件切片的数据
            socket.send(e.target.result);
            // 拿到进度,做进度条
            obj.uploadSchedule = Math.round(loaded / total * 100);
            // if (obj.uploadSchedule < 100) {
            //     // progressTextObj.innerText = '正在读取文件(' + precent + '%)...';
            // } else
            if (loaded >= total) {
                // progressTextObj.innerText = '文件读取完成(100%)';
                socket.send("end");
            }
        },
        loadend: function (e) {
        },
        abort: function (e) {
        },
        error: function (e) {
            // progressTextObj.innerText = "文件读取出错误(~0v0~)";
        }
    })
}
// function sleep(time) {
//     return new Promise(function (resolve) {
//         setTimeout(resolve, time);
//     });
// }
function openSocket(file,obj) {
    var socket
    if (typeof (WebSocket) == "undefined") {
        console.log("您的浏览器不支持WebSocket");
    } else {
        console.log("您的浏览器支持WebSocket");
        //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接
        // var userId = document.getElementById('userId').value;
        var socketUrl = "ws://192.168.1.24:8081/webSocket/" + obj.userName;
        // var socketUrl = "ws://localhost:8081/webSocket/" + name;
        console.log(socketUrl);
        if (socket != null) {
            socket.close();
            socket = null;
        }
        socket = new WebSocket(socketUrl);
        //打开事件
        socket.onopen = function () {
            console.log("websocket已打开",obj);
            readFile(socket,file,obj)
            // WebSocket链接成功建立,可以在这里进行后端交互
            //socket.send("这是来自客户端的消息" + location.href + new Date());
        };

        //获得消息事件
        socket.onmessage = function (msg) {
            var serverMsg = "收到服务端信息:" + msg.data;
            console.log(serverMsg);
            //发现消息进入    开始处理前端触发逻辑
        };
        //关闭事件
        socket.onclose = function () {
            console.log("websocket已关闭");
        };
        //发生了错误事件
        socket.onerror = function () {
            console.log("websocket发生了错误");
        }
    }
}
function closeSocket(socket) {if (socket != null) {
    socket.close();
    socket = null;
    }
}
export function uploadFilesW(file,obj){
    openSocket(file,obj)
 }

页面中使用

<template>
	<div>
		<input type="file" @change="fileChangeF($event,fileId)" />
	</div>
</template>
<script>
import { uploadFilesW } from "../../util/upfile"
export default {
  data(){
    return {
      expDialog:{ // 上传文件弹窗
        dialogVisible:false,
        cloudFile:null, // 云文件
        trajectoryFile:null, // 云文件
        explainFile:null, // 说明文件
        uploadSchedule:0, // 上传进度
        precentState:'',  // 文件上传状态 成功/失败
        showProgressBar:false,  // 进度条展示
        uploadBtncontent:1,
        isUpDisable: false,  // 一个上传完才可以上传下一个
      },
    }
  },
  methods:{
	fileChangeF(eve,type){  // 上传文件选择文件
	      console.log(eve.target.files,type);
	      let fi = eve.target.files
	      let self = this
	      let exp = self.expDialog
	      uploadFilesW(fi[0],this.expDialog)
	      console.log(exp);
	    },
     }
}
</script>

新增需求:对上传文件流进行加密,并传给后端做验证

原文连接:使用React框架 https://www.jb51.net/article/264653.htm

实现方式: fileReader读取文件并 使用md5加密文件

还是在同一个文件中,封装了方法进行调用

安装并引用spark-md5

需要先npm下载 spark-md5

npm i spark-md5 // 安装spark-md5

还是在upfile.js文件(也可以单独放一个文件)

import SparkMD5 from 'spark-md5';
function neverPromise(file) {
    return new Promise(resolve => {	// 因为使用fileReader读取文件是异步的,所以使用promise将加密之后的值返回方便传给后端
        let fileReader = new FileReader(),
        blobSlice =
            File.prototype.mozSlice ||
            File.prototype.webkitSlice ||
            File.prototype.slice,
        // chunkSize = 2097152,
        // read in chunks of 2MB
        chunkSize= 1024 * 1024 * 10,//1MB(单片大小/一兆)
        chunks = Math.ceil(file.size / chunkSize),
        currentChunk = 0,
        spark = new SparkMD5(),
        that = this,
        md5Str ;
        // console.log(Math.ceil(file.size / chunkSize),'file.size / chunkSize');
        // console.log(chunks,'chunks');
        fileReader.onload = function (e) {
            spark.appendBinary(e.target.result);
            // append binary string
            currentChunk++;
            if (currentChunk < chunks) {    // 切片读取完执行
                // 执行这个方法才能短时间内获取到加密后的md5文件?
                loadNext();
            } else {
                let md = spark.end();
                // console.log(file,'file');
                resolve(md.toUpperCase())	// 将数据返回
            }
        };
        function loadNext () {
            let start = currentChunk * chunkSize,
            end = start + chunkSize >= file.size ? file.size : start + chunkSize;
            console.log(blobSlice.call(file, start, end),'blobSlice.call(file, start, end)');
           // readAsBinaryString这个函数看MDN上说是已经弃用,readAsArrayBuffer来代替
           // 但是后来发现这两个函数读取完文件加密后的值不同,为了跟后端同步使用了readAsBinaryString
           //
            fileReader.readAsBinaryString(blobSlice.call(file, start, end));
            // fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
        }
        loadNext();
    })
}
// 在使用的地方调用即可
let md5Send = await neverPromise(file)// 方法记得加async
console.log(md5Send)	// 就可以拿到读取完并加密后的字符串

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue3.0中使用websocket,封装到公共方法的实现

    目录 使用websocket,封装到公共方法 vue中封装websocket问题 1.在untils文件夹下新建socket_service.js 2.在main.js里引用 2.在组件里调用$socket 使用websocket,封装到公共方法 首先创建一个socket.ts文件封装公共方法 /* * @Descripttion: 封装socket方法 * @version: * @Date: 2021-08-06 11:14:39 * @LastEditTime: 2021-10-26 14

  • vue3+ts+Vuex中使用websocket协议方式

    目录 vue3+ts+Vuex使用websocket协议 在stroe中 vue3中 vue封装websocket 封装的socket.js文件内容 使用方法 vue3+ts+Vuex使用websocket协议 本文作者使用的是ts+vue3的setup语法糖,大家注意使用的vue版本! 在stroe中 import { createStore } from 'vuex' import { stateInt } from '../interface/storeInterface' const s

  • Vue websocket封装实现方法详解

    目录 1.封装的ws.js文件 2.使用方法 1.封装的ws.js文件 let global_callback = null let socket = '' // 存储 WebSocket 连接. let timeoutObj = null // 心跳定时器 let serverTimoutObj = null // 服务超时定时关闭 let lockReconnect = false // 是否真正建立了连接 let timeoutnum = null // 重新连接的定时器, 没连接上会一直

  • vue项目使用websocket连接问题及解决

    目录 vue使用websocket连接 前景 解决过程 vue2全局使用websocket记录 新建ws模块文件 在main.js中引用ws模块文件 App.vue挂载时再次连接服务器并且接收消息 vue使用websocket连接 前景 公司做一个包含websocket的项目,我用的是vue做的,开始只有一个组件的要求demo,就将websocket的配置直接放在组件方法中,组件挂载时直接初始化ws,但是后续组件增加,开始出现多个websocket链接的情况,是不允许的. 刚开始的做法是将web

  • vue使用websocket概念及示例

    目录 概念部分: 使用示例 概念部分: 1,WebSocket 是 HTML5 提供的 TCP 连接上进行全双工通讯的协议.一次握手之后,服务器和客户端可以互相主动通信,双向传输数据. 2,浏览器想服务器发送请求,建立连接之后,可通过send()方法想服务器发送数据,并通过message事件接受服务器返回的数据. 使用示例 <script> export default { mounted() { this.connectWebsocket(); }, methods: { connectWe

  • Vue项目使用Websocket大文件FileReader()切片上传实例

    目录 使用技术 upfile.js文件 新增需求:对上传文件流进行加密,并传给后端做验证 还是在upfile.js文件(也可以单独放一个文件) 大文件上传,本地1.3G文件不到一分钟上传完毕 使用技术 Vue框架 WebSocket双向传输 FileReader读取文件 封装的WebSocket请求文件上传方法,目前只支持单文件上传,有研究出来多文件上传,记得评论哦 upfile.js文件 //file.slice(起始字节,终止字节)与FileReader实现文件切片读取 function P

  • iOS大文件的分片上传和断点上传的实现代码

    今天小编抽空给大家分享一些大文件的上传的问题!断点续传和分片上传.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传.所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这

  • SpringCloud大文件分片断点上传实现原理

    1背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通过浏览器上传至服务器,做一层中转便可以实现,但当这份文件非常大到了10GB级别,我们就需要思考另一种形式的技术方案了,也就是本文要阐述的方案. 技术要求主要有以下几方面: 支持超大数据量.10G级别以上 稳定性:除网络异常情况100%成功 准确性:数据无丢失,读写准确性100% 效率:1G文件分钟级.

  • php表单文件iframe异步上传实例讲解

    本文实例为大家分享了php表单文件iframe异步上传的具体代码,供大家参考,具体内容如下 1.表单中放置iframe元素: 2.文件上传控件内容变化的时候触发JS设置表单的action为处理文件上传的img_upload_process.php文件,并且将表单的target设置为iframe,让iframe去提交到服务器进行文件上传: 3.img_upload_process.php中处理文件上传成功后,将上传成功保存的文件路径回传给表单中隐藏域: 4.点击表单提交按钮的时,JS设置表单act

  • php多个文件及图片上传实例详解

    本文实例讲述了php多个文件及图片上传的方法.分享给大家供大家参考.具体实现方法如下: 多个文件上传是在单文件上传的基础上利用遍历数组的方式进行遍历表单数组然后把文件一个个上传到服务器上了,下面就来看一个简单多个文件上传实例 多个文件上传和单独文件上传的处理方式是一样的,只需要在客户端多提供几个类型为"file"的输入表单,并指定不同的"name"属性值.例如,在下面的代码中,可以让用户同时选择三个本地文件一起上传给服务器,客户端的表单如下所示: 复制代码 代码如下

  • PHP大文件分割分片上传实现代码

    服务端为什么不能直接传大文件?跟php.ini里面的几个配置有关 upload_max_filesize = 2M //PHP最大能接受的文件大小 post_max_size = 8M //PHP能收到的最大POST值' memory_limit = 128M //内存上限 max_execution_time = 30 //最大执行时间 当然不能简单粗暴的把上面几个值调大,否则服务器内存资源吃光是迟早的问题. 解决思路 好在HTML5开放了新的FILE API,也可以直接操作二进制对象,我们可

  • asp.net javascript 文件无刷新上传实例代码第1/2页

    在新增数据项的时候,用ajax实现无刷新提交,但上传文件的时候,由于数据类型原因,不能将页面的<asp:FileUpload>中以字符串值的方式传到js里调用.我一共找到了两个方法予以解决,实现无刷新上传. 第一种方法:利用js的ADODB.Stream,将文件先转换成流,再通过js上传到服务器,这样有个好处就是可以上传超大文件,并且由于是数据流,可以支持断点续传.方便显示上传进度等人性化功能.唯一的缺点是要客户端浏览器需要设置安全级别,或者安装相关ActiveX控件(这个控件自己做的,加载到

  • vue 文件切片上传的项目实现

    目录 流程简说 获取文件的 MD5 唯一标识码 文件切片 获取文件名 name 分片文件大小 chunkSize 文件切片 chunkList 列表 切片总数 chunks 切片大小 size 合并 在实际开发项目过程中有时候需要上传比较大的文件,然后呢,上传的时候相对来说就会慢一些,so,后台可能会要求前端进行文件切片上传,很简单哈,就是把比如说1个G的文件流切割成若干个小的文件流,然后分别请求接口传递这个小的文件流. 流程简说 实现文件切片导入,首先我们使用 elementUI 也好,原生的

  • js自己实现一个大文件切片上传+断点续传的示例代码

    目录 首先我们来分析一下需求 一. 格式校验 二. 文件切片 三. 断点续传 + 秒传 + 上传进度 PM:喂,那个切图仔,我这里有个100G的视频要上传,你帮我做一个上传后台,下班前给我哦,辛苦了.我:...相信每个切图工程师,都接触过文件上传的需求,一般的小文件,我们直接使用 input file,然后构造一个 new FormData()对象,扔给后端就可以了.如果使用了 Ant design 或者 element ui 之类的ui库,那更简单,直接调用一下api即可.当然了,复杂一些的,

  • JavaScript大文件上传的处理方法之切片上传

    目录 前言 切片后上传 生成hash 文件秒传 暂停上传 中断请求示例 添加暂停上传功能 恢复上传 添加功能总结 前言 本篇介绍了切片上传的基本实现方式(前端),以及实现切片上传后的一些附加功能,切片上传原理较为简单,代码注释比较清晰就不多赘述了,后面的附加功能介绍了实现原理,并贴出了在原本代码上的改进方式.有什么错误希望大佬可以指出,感激不尽. 切片后上传 切片上传的原理较为简单,即获取文件后切片,切片后整理好每个切片的参数并发请求即可. 下面直接上代码: HTML <template> &

随机推荐