整理前端工作中的可复用代码(二):拓展spark-md5,支持计算网络文件md5

栏目: 服务器 · 发布时间: 5年前

内容简介:在工作中接到一个需求,需要在浏览器端计算文件的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功能,便封装了一个插件。

整理前端工作中的可复用代码(二):拓展spark-md5,支持计算网络文件md5

使用方式:

<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

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》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换