前端页面使用js计算文件的md5和sha256

一篇纯代码的文章。更多的说明在代码中

<template>
  <div>
    <input type="file" @change="calculate" />
  </div>
</template>

<script>
  import CryptoJs from 'crypto-js'
  import encHex from 'crypto-js/enc-hex'

  /**
   * 用于计算文件的hash值,包括sha256值和md5值
   */
  function hashFile (file) {
    /**
     * 使用指定的算法计算hash值
     */
    function hashFileInternal (file, alog) {
      // 指定块的大小,这里设置为20MB,可以根据实际情况进行配置
      const chunkSize = 20 * 1024 * 1024
      let promise = Promise.resolve()
      // 使用promise来串联hash计算的顺序。因为FileReader是在事件中处理文件内容的,必须要通过某种机制来保证update的顺序是文件正确的顺序
      for (let index = 0; index < file.size; index += chunkSize) {
        promise = promise.then(() => hashBlob(file.slice(index, index + chunkSize)))
      }

      /**
       * 更新文件块的hash值
       */
      function hashBlob (blob) {
        return new Promise((resolve, reject) => {
          const reader = new FileReader()
          reader.onload = ({ target }) => {
            const wordArray = CryptoJs.lib.WordArray.create(target.result)
            // 增量更新计算结果
            alog.update(wordArray)
            resolve()
          }
          reader.readAsArrayBuffer(blob)
        })
      }

      // 使用promise返回最终的计算结果
      return promise.then(() => encHex.stringify(alog.finalize()))
    }

    // 同时计算文件的sha256和md5,并使用promise返回
    return Promise.all([hashFileInternal(file, CryptoJs.algo.SHA256.create()),
                        hashFileInternal(file, CryptoJs.algo.MD5.create())])
      .then(([sha256, md5]) => ({
        sha256,
        md5
      }))
  }

  export default {
    methods: {
      calculate ({ target: { files } }) {
        for (const file of files) {
          hashFile(file).then(console.log)
        }
      }
    }
  }
</script>

代码是一个vue组件,但没有用到特殊的vue方法,仅仅是调试的时候用了它而已。代码理论上可以用于任何框架。

代码的核心是crypto-js库的使用。

通过对文件进行切片和增量更新hash的方式对文件进行hash计算,可以避免浏览器out of memory错误

使用异步计算hash值,计算返回promise,在promise.then()中获取计算结果

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。