繁体   English   中英

md5 以增量方式散列大文件?

[英]md5 hash a large file incrementally?

在浏览器中,我使用 JS FileReader().readAsBinaryString() 读入文件。 使用 CryptoJS 库,我可以对数据进行 MD5 散列。

这工作正常,但我不知道如何处理大文件。 例如,仅读取 2GiB 文件就会使浏览器窗口崩溃。 我可以从文件数据中切出 blob 并进行散列,但这不会阻止其他人在不遵循与我相同的步骤的情况下验证相同的散列吗?

在这种情况下,有没有办法获取大文件的 md5 哈希值? 例如,您将如何计算 1TB 文件的 md5 哈希值? 我需要以流的形式读取文件吗?

第一次在这个上切牙,我不知道该怎么做。

这驻留在角度指令中,因此范围。

var reader = new FileReader();
                reader.onload = function (loadEvent) {
                    scope.$apply(function () {
                        scope.files = changeEvent.target.files;
                        scope.fileread = loadEvent.target.result;
                        scope.md5Data = CryptoJS.MD5(scope.fileread).toString();
                    });
                }
                // First ten megs of the file
                reader.readAsBinaryString((changeEvent.target.files[0]).slice(0, 10 * 1024 * 1024));

使用spark-md5Q

由于其他答案都没有提供完整的片段,因此您将如何计算大文件的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="https://cdnjs.cloudflare.com/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>

使用SparkMD5 https://github.com/satazor/SparkMD5

var spark = new SparkMD5(); 
spark.append('Hi');
spark.append('there');
var hexHash = spark.end();

它有一个文件切片示例

我可以从文件数据中切出 blob 并进行散列,但这不会阻止其他人在不遵循与我相同的步骤的情况下验证相同的散列吗?

是的,因此这正是 MD5 算法在其合同中提供的内容:

  1. 你有一个文件
  2. 通过添加单个“1”和多个“0”来填充文件,因此该文件可被 512 整除。
  3. 每轮计算文件的 512 字节切片的 md5 哈希值,并将其与前一个结果组合。

因此,您无需重复这些步骤并确保其他用户也这样做。

由于 MD5 是按块计算的,因此流式传输是可能的,正如您在此处阅读的那样(尽管使用 nodejs 的 crypt 模块完成,它是 googlecode 项目 crypto-js 的模块化端口。):

http://www.hacksparrow.com/how-to-generate-md5-sha1-sha512-sha256-checksum-hashes-in-node-js.html

您可能需要检查 CryptoJS 站点上的段落渐进散列

这个例子:

var sha256 = CryptoJS.algo.SHA256.create();
sha256.update("Message Part 1");
sha256.update("Message Part 2");
sha256.update("Message Part 3");
var hash = sha256.finalize();

MD5和 presto 替换SHA256 (也重命名变量,我会让你选择一个好名字)。

用法:

const md5 = await incrementalMD5(file)

incrementalMD5来源:

import SparkMD5 from 'spark-md5'

export const incrementalMD5 = file =>
  new Promise((resolve, reject) => {
    const fileReader = new FileReader()
    const spark = new SparkMD5.ArrayBuffer()
    const chunkSize = 2097152 // Read in chunks of 2MB
    const chunks = Math.ceil(file.size / chunkSize)
    let currentChunk = 0

    fileReader.onload = event => {
      spark.append(event.target.result) // Append array buffer
      ++currentChunk
      currentChunk < chunks ? loadNext() : resolve(spark.end()) // Compute hash
    }

    fileReader.onerror = () => reject(fileReader.error)

    const loadNext = () => {
      const start = currentChunk * chunkSize
      const end = start + chunkSize >= file.size ? file.size : start + chunkSize
      fileReader.readAsArrayBuffer(File.prototype.slice.call(file, start, end))
    }

    loadNext()
  })

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM