如何计算使用JavaScript的文件的MD5散列
在使用Javascript上传到服务器之前,有没有办法计算文件的MD5散列?
虽然有MD5algorithm的JS实现 ,但旧版浏览器通常无法从本地文件系统读取文件 。
我在2009年写了这个。那么新浏览器呢?
使用支持FileAPI的浏览器,您可以*读取文件的内容 – 用户必须使用<input>
元素或拖放操作来select它。 截至2013年1月,以下是主要浏览器如何堆叠:
- FF 3.6支持FileReader ,FF4支持更多基于文件的function
- Chrome自7.0.517.41版开始支持FileAPI
- Internet Explorer 10具有部分FileAPI支持
- Opera 11.10 部分支持FileAPI
- Safari浏览器 – 我找不到一个好的官方来源,但这个网站build议从5.1的部分支持,完全支持6.0 。 另一篇文章报道了一些与旧版Safari不一致的地方
我做了一个实现增量md5的库,以便高效地散列大文件。 基本上,你读取一个文件块(保持低的内存),并散列散列。 自述文件中提供了基本的用法和示例。
请注意,您需要HTML5 FileAPI,所以一定要检查它。 testing文件夹中有一个完整的例子。
使用CryptoJS的MD5函数和HTML5 FileReader API来计算MD5哈希非常容易。 以下代码片段显示了如何读取二进制数据,并从拖动到浏览器的图像计算MD5哈希:
var holder = document.getElementById('holder'); holder.ondragover = function() { return false; }; holder.ondragend = function() { return false; }; holder.ondrop = function(event) { event.preventDefault(); var file = event.dataTransfer.files[0]; var reader = new FileReader(); reader.onload = function(event) { var binary = event.target.result; var md5 = CryptoJS.MD5(binary).toString() console.log(md5); }; reader.readAsBinaryString(file); };
我build议添加一些CSS来查看拖放区域:
#holder { border: 10px dashed #ccc; width: 300px; height: 300px; } #holder.hover { border: 10px dashed #333; }
关于拖放function的更多信息可以在这里find: File API和FileReader
我在Google Chrome 32版中testing了这个示例。
您需要使用FileAPI。 它是在最新的FF和Chrome,但不是IE9。 抓住上面build议的任何md5 JS实现。 我试过这个,放弃了,因为JS太慢(在大图像文件分钟)。 如果有人用键入的数组重写MD5,可能会重新访问它。
代码看起来像这样:
HTML: <input type="file" id="file-dialog" multiple="true" accept="image/*"> JS (w JQuery) $("#file-dialog").change(function() { handleFiles(this.files); }); function handleFiles(files) { for (var i=0; i<files.length; i++) { var reader = new FileReader(); reader.onload = function() { var md5 = binl_md5(reader.result, reader.result.length); console.log("MD5 is " + md5); }; reader.onerror = function() { console.error("Could not read the file"); }; reader.readAsBinaryString(files.item(i)); } }
除了不可能在JS中获得文件系统访问,我不会在客户端生成的校验和中放任何信任。 所以在服务器上生成校验和是强制性的。 – – Tomalak 4月20 '09在14:05
在大多数情况下,这是无用的。 你需要在客户端计算MD5,以便你可以将它与在服务器端重新计算的代码进行比较,并且如果它们不同,则认为上载出错了。 在使用科学数据的大型文件的应用程序中,我需要这样做,因为接收未损坏的文件是关键。 我的情况很简单,因为用户已经从他们的数据分析工具中计算出了MD5,所以我只需要用文本字段向他们提问。
为了获得文件的散列,有很多选项。 通常问题是获取大文件的散列速度非常慢。
我创build了一个小文件库,获取文件的哈希值,文件的开始64kb和结束的64kb。
现场示例: http : //marcu87.github.com/hashme/和库: https : //github.com/marcu87/hashme
HTML5 + spark-md5
和Q
假设你使用一个现代的浏览器(支持HTML5的文件API),这里是如何计算一个大文件的MD5散列 (它将计算可变块上的散列)
function calculateMD5Hash(file, bufferSize) { var def = Q.defer(); var fileReader = new FileReader(); var fileSlicer = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; var hashAlgorithm = new SparkMD5(); var totalParts = Math.ceil(file.size / bufferSize); var currentPart = 0; var startTime = new Date().getTime(); fileReader.onload = function(e) { currentPart += 1; def.notify({ currentPart: currentPart, totalParts: totalParts }); var buffer = e.target.result; hashAlgorithm.appendBinary(buffer); if (currentPart < totalParts) { processNextPart(); return; } def.resolve({ hashResult: hashAlgorithm.end(), duration: new Date().getTime() - startTime }); }; fileReader.onerror = function(e) { def.reject(e); }; function processNextPart() { var start = currentPart * bufferSize; var end = Math.min(start + bufferSize, file.size); fileReader.readAsBinaryString(fileSlicer.call(file, start, end)); } processNextPart(); return def.promise; } function calculate() { var input = document.getElementById('file'); if (!input.files.length) { return; } var file = input.files[0]; var bufferSize = Math.pow(1024, 2) * 10; // 10MB calculateMD5Hash(file, bufferSize).then( function(result) { // Success console.log(result); }, function(err) { // There was an error, }, function(progress) { // We get notified of the progress as it is executed console.log(progress.currentPart, 'of', progress.totalParts, 'Total bytes:', progress.currentPart * bufferSize, 'of', progress.totalParts * bufferSize); }); }
<script src="ajax/libs/q.js/1.4.1/q.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/2.0.2/spark-md5.min.js"></script> <div> <input type="file" id="file"/> <input type="button" onclick="calculate();" value="Calculate" class="btn primary" /> </div>
在互联网上有几个脚本来创build一个MD5哈希。
从webtoolkit的一个是好的, http://www.webtoolkit.info/javascript-md5.html
虽然,我不相信它将有权访问本地文件系统,因为访问是有限的。
使用当前的HTML5,应该可以计算二进制文件的md5散列,但是我认为之前的步骤是将银行数据BlobBuilder转换为string,我正在尝试执行此步骤:但尚未成功。
这是我尝试的代码: 在HTML5 JavaScript中将BlobBuilder转换为string
我不相信有一种方法在JavaScript访问file upload的内容。 所以你不能看文件内容来生成一个MD5总和。
但是,您可以将文件发送到服务器,然后可以发送一个MD5总和或发送文件内容..但这是很多的工作,可能不值得为您的目的。
那么可以用HTML5 File API读取文件(请参阅Blob界面)。 没有testing,但你可以做到这一点。
另外,你永远不要相信客户。 一旦它被上传,你只需要重做哈希。
没有插件,你不能访问二进制数据。 你应该看看使用基于Flash的上传工具。 我有使用SWFUpload的同事,但我不知道如何访问文件内容本身。 你可能不得不改变SWF本身来允许这个。