大文件上传,本地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)	// 就可以拿到读取完并加密后的字符串

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

Vue项目使用Websocket大文件FileReader()切片上传实例的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. 五分钟学会HTML5的WebSocket协议

    这篇文章主要介绍了五分钟学会HTML5的WebSocket协议,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. 前端监听websocket消息并实时弹出(实例代码)

    这篇文章主要介绍了前端监听websocket消息并实时弹出,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. 浅谈HTML5 FileReader分布读取文件以及其方法简介

    本篇文章主要介绍了浅谈HTML5 FileReader分布读取文件以及其方法简介,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  6. ios – Websockets可以在移动电话上工作吗?

    相关地,我怀疑长轮询客户端可能是实现类似功能的好方法,但我想知道我可能遇到的移动特定问题.到目前为止,我已经读过长时间的轮询请求可能会对电池寿命产生相当大的影响.我还听说iOS以某种方式限制了对单个服务器的连接数量,这可能是个问题.有没有人在使用实时组件的移动应用程序上工作?

  7. ios-swift,objective-c协议实现

    作为隐式解开的可选项.

  8. ios – 红蜘蛛代表没有被召集

    变量不是nil,我有一个很好的连接,url是正确的,但没有调用委托方法.我也正在实现WebSocketDelegate解决方法套接字应该是您的类的属性或变量,以确保它附近.如果仅在函数堆栈上分配它,它将超出范围,并且永远不会调用委托以下是我在项目中使用的代码,以防万一这是link到故事板,以防万一你想要

  9. swift 实现websocket与后台通信(swift 如何构建简单的json字符串)

    一个应用不可避免要与服务器进行通信,主要有,http与socket。http暂时不论,我们先看看socket下面衍生的websocket,今天我就把自己怎么利用websocket与服务器进行交互记录下来:首先你需要集成websocket到自己的项目,如果不明白如何集成,请看上一篇《swift集成websocket库》集成websocket到自己项目后还需要添加SwiftyJSON到自己项目,具体步骤和集成websocket一样。首先打开你项目,记得通过cocoapods生成的.xcworkspace文件打

  10. 如何在Android上托管REST webservices?

    有没有人知道一个用Java编写的能够在Android上托管REST服务的开源Web服务器?

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部