yokila
yokila
Published on 2021-03-04 / 21 Visits
0
0

JS的MD5和SHA256摘要生成使用并对异步处理问题进行解决

import SparkMD5 from 'spark-md5'

import CryptoJS from 'crypto-js'



/**

 * 依据指定摘要算法生成hash摘要

 */

export function digestGeneration (digest, file) {

  return new Promise(function (resolve, reject) {

    // element 中组件对 file 进行加工,这里使用未加工的对象,只有未加工的对象才能在 blobSlice.call() 中正常操作

    let fileRaw = file.raw

    // 创建md5

    let spark = new SparkMD5()

    // 创建sha256

    let sha256 = CryptoJS.algo.SHA256.create()

    // 使得支持多种浏览器的文件读取

    let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice

    let fileReader = new FileReader()

    let chunkSize = 1024 // 分割的块的大小最大为1k

    let chunks = Math.ceil(file.size / chunkSize)

    let currentChunk = 0

    let result

    // fileReader文件读取成功时触发的事件定义

    fileReader.onload = function (e) {

      // 依据传过来的摘要算法选择进行区分使用的摘要算法

      if (digest === '0') {

        spark.append(e.target.result)

      } else if (digest === '1') {

        sha256.update(arrayBufferToWordArray(e.target.result))

      }

      currentChunk++

      if (currentChunk < chunks) {

        loadNext()

      } else {

        // 依据传过来的摘要算法选择进行返回结果的摘要算法

        if (digest === '0') {

          result = spark.end()

        } else if (digest === '1') {

          let res = sha256.finalize()

          result = res.toString(CryptoJS.enc.Hex).toLowerCase()

        }

        resolve(result)

      }

    }

    // 文件读取失败时触发

    fileReader.onerror = function () {

      this.$message.error('文件读取出错!')

    }

    // 读取操作

    function loadNext () {

      let start = currentChunk * chunkSize

      let end = start + chunkSize >= file.size ? file.size : start + chunkSize

      fileReader.readAsArrayBuffer(blobSlice.call(fileRaw, start, end))

    }

    // 开始执行fileReader读取文件

    loadNext()

  })

}



/**

 * arraybuffer to wordarray 的转换函数

 */

function arrayBufferToWordArray (ab) {

  let i8a = new Uint8Array(ab)

  let a = []

  for (let i = 0; i < i8a.length; i += 4) {

    a.push(i8a[i] << 24 | i8a[i + 1] << 16 | i8a[i + 2] << 8 | i8a[i + 3])

  }

  return CryptoJS.lib.WordArray.create(a, i8a.length)

}

注意:

  1. 传入的digest判断(区分本次使用的是MD5还是SHA256)用的是'1'和'0'而不是1和0

  2. result是要返回的数据

  3. 这里是对文件进行摘要生成

  4. 本文内容可单独形成一个工具文件

  5. 下一篇将有本篇的具体实例使用

PS:

小菜鸟,有问题请提出,使用过程可以自行优化


Comment