内容简介:在工作中接到一个需求,需要在浏览器端计算文件的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时,请慎用。如果哪位大神有更好的解决办法,还请分享下。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming in Haskell
Graham Hutton / Cambridge University Press / 2007-1-18 / GBP 34.99
Haskell is one of the leading languages for teaching functional programming, enabling students to write simpler and cleaner code, and to learn how to structure and reason about programs. This introduc......一起来看看 《Programming in Haskell》 这本书的介绍吧!