内容简介:在工作中接到一个需求,需要在浏览器端计算文件的md5值,然后在上传文件时传递给后端储存。按照以往的思路,后端只需要三两行代码即可实现,比如使用php中的md5_file。然而文件并不是上传到后端服务器,而是直接上传到阿里云的oss。如果后端去请求oss上的文件计算md5,就容易造成服务器的压力,所以计算文件md5的最好方式是交给客户端实现。尽管以前没有接触过浏览器端计算文件md5,但在谷歌、百度搜索一番后,便用spark-md5解决了这一需求。但如果事情就这样结束了的话,就没有后续计算网络文件md5的想法,
在工作中接到一个需求,需要在浏览器端计算文件的md5值,然后在上传文件时传递给后端储存。按照以往的思路,后端只需要三两行代码即可实现,比如使用 php 中的md5_file。
<?php $filename = "file.jpg"; $md5 = md5_file($filename); echo $md5; ?> 复制代码
然而文件并不是上传到后端服务器,而是直接上传到阿里云的oss。如果后端去请求oss上的文件计算md5,就容易造成服务器的压力,所以计算文件md5的最好方式是交给客户端实现。
尽管以前没有接触过浏览器端计算文件md5,但在谷歌、百度搜索一番后,便用spark-md5解决了这一需求。但如果事情就这样结束了的话,就没有后续计算网络文件md5的想法,以及这篇文章的出现了。
接着计算本地文件md5的需求,又接到了一个需求。上传的图片要进行压缩,压缩使用plupload的自带功能实现,而压缩后的图片md5已改变。经过一些时间还没有找到解决方案,加上技术总监对我说项目后续要增加新东西,让我最好在审核上传资源的时候计算md5,这样便开始了前端计算网络文件md5的摸索。
File 对象
在谷歌、百度了N久之后,没有找到一个准确的答案,包括flash方案。我想应该很少有在浏览器端计算网络文件md5的需求或实现,也展开了自己的一些猜想。
第一应该先要有一个文件,然后从文件中计算md5,类似:
var file = new File(['www.domain.com/test.jpg'], 'test.jpg', {type: 'images/jpg'}); 复制代码
然而File对象并不接收url参数来生成文件,这里的url被当成字符串处理了,这不是想要的答案。
Blob 对象
Blob对象是一个类文件对象,File对象继承于Blob对象,它们的用法类似,Blob也不能直接处理url为Blob对象。但要计算文件md5,需要FileReader读取一个File或Blob对象,再由spark-md5进一步计算得出md5。
所幸在XMLHttpRequest中可以指定responseType为blod,请求文件并指定responseType为blod时,XMLHttpRequest将返回一个Blob对象,相关介绍可参考这里responseType,如下:
var request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'blob'; request.onload = function() { //类似Blob(3275) {size: 3275, type: "image/vnd.microsoft.icon"} console.log(request.response); }; request.send(); 复制代码
至此,下一步便可以用spark-md5计算Blob对象来返回md5了( spark-md5官方示例 )。
var request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'blob'; request.onload = function() { var file = request.response; var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, chunkSize = 2097152, // Read in chunks of 2MB chunks = Math.ceil(file.size / chunkSize), currentChunk = 0, spark = new SparkMD5.ArrayBuffer(), fileReader = new FileReader(); fileReader.onload = function (e) { spark.append(e.target.result); currentChunk++; if (currentChunk < chunks) { loadNext(); } else { //获取md5 var md5 = spark.end(); console.log(md5); } }; fileReader.onerror = function () { console.error('文件读取失败'); }; function loadNext() { var start = currentChunk * chunkSize, end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); } loadNext(); }; request.send(); 复制代码
拓展spark-md5
通过上面的代码,便实现了浏览器端js计算网络文件的md5。而据spark-md5的使用方式,直接计算字符串md5时比较简单:
SparkMD5.hash('hello world');//"5eb63bbbe01eeed093cb22bb8f5acdc3" 复制代码
如上只需要一行代码即可,但在计算文件时略复杂些,代码不利于复用。出于本系列文章整理可复用代码的初衷,以及想要加入计算网络文件md5功能,便封装了一个插件。
- github地址: md5-util
- 演示: md5-util demo,下方附二维码
使用方式:
<script src="md5-util.min.js"></script> 复制代码
//计算本地文件md5 SparkMD5.file(file,function(md5){ console.log(md5) }) //计算网络文件md5 SparkMD5.file(url,function(md5){ console.log(md5) }) 复制代码
这里参考过 browser-md5-file ,不同的是此插件只扩展了spark-md5,增加了file方法,spark-md5的所有方法均可在插件中使用。
浏览器兼容性
这里只讨论计算网络文件md5的兼容性,在pc端一些主流浏览器中测试了多次,得出的md5均是正确的。但由于XMLHttpRequest的responseType指定为blob,在移动端发现一些兼容性问题,已知ios uc浏览器及安卓5.1.1系统浏览器中返回blob异常,导致md5计算错误。
所以要计算网络文件的md5时,请慎用。如果哪位大神有更好的解决办法,还请分享下。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ruby Cookbook
Lucas Carlson、Leonard Richardson / O'Reilly Media / 2006-7-29 / USD 49.99
Do you want to push Ruby to its limits? The "Ruby Cookbook" is the most comprehensive problem-solving guide to today's hottest programming language. It gives you hundreds of solutions to real-world pr......一起来看看 《Ruby Cookbook》 这本书的介绍吧!