当前位置: 代码网 > it编程>编程语言>Javascript > 如何使用crypto-js对文件上传下载进行加密处理

如何使用crypto-js对文件上传下载进行加密处理

2024年06月11日 Javascript 我要评论
由于文件安全问题,要求上传文件的时候,把文件流加密后传递给后端,且下载的时候,解密后,方可下载文件。有两种方法、一种将文件转base64加密 一种是转二进制数据加密、由于base64会将原文件大小变大

由于文件安全问题,要求上传文件的时候,把文件流加密后传递给后端,且下载的时候,解密后,方可下载文件。

有两种方法、一种将文件转base64加密 一种是转二进制数据加密、由于base64会将原文件大小变大很多倍,二进制不会、因此推荐使用方法二。

以下是相关代码:

方法一

1、引入crypto-js

并封装加密、解密的方法,具体代码如下:

// utils/jsencrypt.js
import cryptojs from 'crypto-js';
 
 
// des加密
export const encryptbydes = (message, key) => {
  var keyhex = cryptojs.enc.utf8.parse(key);
  var encrypted = cryptojs.aes.encrypt(message, keyhex, {
      mode: cryptojs.mode.ecb,
      padding: cryptojs.pad.pkcs7
  });
  return encrypted.tostring();
}
 
// des解密
export const decryptbydes = (ciphertext, key) => {
var keyhex = cryptojs.enc.utf8.parse(key);
// direct decrypt ciphertext
var decrypted = cryptojs.aes.decrypt({
    ciphertext: cryptojs.enc.base64.parse(ciphertext)
}, keyhex, {
    mode: cryptojs.mode.ecb,
    padding: cryptojs.pad.pkcs7
});
return decrypted.tostring(cryptojs.enc.utf8);
}

2、文件上传时加密

页面:

 <el-upload
      action="#"
      :before-upload="handlebeforeupload"
      :file-list="filelist"
      :limit="1"
      :on-error="handleuploaderror"
      :on-exceed="handleexceed"
      :on-success="handleuploadsuccess"
      :show-file-list="false"
      :headers="headers"
      :http-request="handlefileupload"
      class="upload-file-uploader"
      ref="upload"
    >
      <!-- 上传按钮 -->
      <el-button size="mini" type="primary" :loading="loading">选取文件</el-button>
      <!-- 上传提示 -->
      <div class="el-upload__tip" slot="tip" v-if="showtip">
        请上传
        <template v-if="filesize"> 大小不超过 <b style="color: #f56c6c">{{ filesize }}mb</b> </template>
        <template v-if="filetype"> 格式为 <b style="color: #f56c6c">{{ filetype.join("/") }}</b> </template>
        的文件
      </div>
    </el-upload>

上传文件(加密文件):

首先使用filereader中readasdataurl将上传的文件流转成base64字符串,然后使用加密事件将base64字符串加密,传递给后端。

// 上传文件
handlefileupload(file){
      this.loading = true
      let reader = new filereader()
      reader.readasdataurl(file.file) // 读取base64
      reader.onload = ()=>{
        // reader.result 读取base64
        // 使用 aes 算法对 reader 进行加密
        let encrypted = encryptbydes(reader.result, 'abcdefghijklmno12345678910234567') // 此加密key可自定义
        this.base64string = encrypted
        // 获取文件类型
        this.filetypes = file.file.name.substring(file.file.name.lastindexof("."))
        let params = {
          filename:file.file.name,
          filetype:this.filetypes,
          filesize:file.file.size,
          base64:this.base64string // 将加密后的文件字符串传给后端
        }
        getfileupload(params).then((res)=>{
        this.loading = false
          this.$message.success("上传成功");
          this.filename=res.filename
          console.log(this.filename,'this.filename')
          this.$emit("input", res.fileid);
          this.$emit('filename',this.filename)
        }).catch((error)=>{
          this.loading = false
          this.$message.error("上传失败, 请重试");
          console.log(error,'error')
          this.filelist = []
          this.list = []
        })
      }
},

下载文件(解密文件):

先将获取到的加密串解密,然后将base64串转成blob格式,然后下载文件,具体代码如下:

// 通过接口获取到加密字符串files
keyfiles(params).then((files)=>{
// 将加密字符串files解密
let base64url =                 decryptbydes(files,'abcdefghijklmno12345678910234567')
                        // 将解密到的base64字符串转成blob格式
                        let blob = this.base64toblob(base64url)
                        // 下载文件
                        this.blobdownload(blob,this.listparams.filename)
                        this.$set(row, 'loading', false)
                      })
base64toblob(datauri) {
      // 将 datauri 分割为类型和数据两部分
      var parts = datauri.split(",");
      var type = parts[0].match(/:(.*?);/)[1];
      var data = parts[1];
 
      // 将 base64 数据解码为二进制数据
      var bytestring = atob(data);
 
      // 将二进制数据转换为类型化数组
      var arraybuffer = new arraybuffer(bytestring.length);
      var intarray = new uint8array(arraybuffer);
 
      for (var i = 0; i < bytestring.length; i++) {
        intarray[i] = bytestring.charcodeat(i);
      }
      // 创建一个 blob 对象
      var blob = new blob([intarray], { type: type });
      return blob;
    },
blobdownload(blob,filename){
      // 判断浏览器类型
      if (window.navigator && window.navigator.mssaveoropenblob) {
        // 如果是 ie 浏览器,使用 mssaveoropenblob 方法
        window.navigator.mssaveoropenblob(blob, filename);
      } else {
        var myurl = url.createobjecturl(blob); //创建图片的临时url
        // downloadfile(myurl,name)
        var a = document.createelement("a") //新建一个a链接
        a.setattribute("href",myurl) // a链接的url为图片的url
        a.setattribute("download",filename)
        a.setattribute("target","_blank")
        let clickevent = document.createevent("mouseevents");
        clickevent.initevent("click", true, true);
        a.dispatchevent(clickevent);
      }
    },

由于要支持ie浏览器,注意crypto-js的版本,一开始使用4.1.1 不支持ie,后面改成4.0.0即可。

方法二

由于将文件转成base64加密后使文件大小比之前大了很多倍,存到服务器很不友好,于是使用二进制进行加解密、保持与之前大小一致,具体如下:

1、封装加密、解密的方法

 
import cryptojs from 'crypto-js';
import cryptou8array from "./crypto-en"
var key = cryptojs.enc.utf8.parse("1111111111111111"); //十六位十六进制数作为秘钥
var iv = cryptojs.enc.utf8.parse('1111111111111111');//十六位十六进制数作为秘钥偏移量
// 使用 aes 进行文件加密  
export function encryptfile(word) {  
  const messagewordarray = cryptou8array.u8array.parse(word);
  var encrypted = cryptojs.aes.encrypt(messagewordarray, key, {
        iv: iv,
        mode: cryptojs.mode.cbc,
        padding: cryptojs.pad.pkcs7
    });
  let encryptedbytes = encrypted.ciphertext
  return cryptou8array.u8array.stringify(encryptedbytes) 
}  
// 使用 aes 进行文件解密  
export function decryptfile(word) {  
  const messagewordarray = cryptou8array.u8array.parse(word);
  var dcbase64string = messagewordarray.tostring(cryptojs.enc.base64);
  var decrypt = cryptojs.aes.decrypt(dcbase64string, key, {
      iv: iv,
      mode: cryptojs.mode.cbc,
      padding: cryptojs.pad.pkcs7
  });
  // var decryptedstr = decrypt.tostring(cryptojs.enc.utf8);
  return cryptou8array.u8array.stringify(decrypt)
}  
// crypto-en.js
import cryptojs from 'crypto-js'
cryptojs.enc.u8array = {
  /**
   * converts a word array to a uint8array.
   *
   * @param {wordarray} wordarray the word array.
   *
   * @return {uint8array} the uint8array.
   *
   * @static
   *
   * @example
   *
   * var u8arr = cryptojs.enc.u8array.stringify(wordarray);
   */
  stringify: function (wordarray) {
    // shortcuts
    var words = wordarray.words
    var sigbytes = wordarray.sigbytes
    // convert
    var u8 = new uint8array(sigbytes)
    for (var i = 0; i < sigbytes; i++) {
      var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
      u8[i] = byte
    }
    return u8
  },
  /**
   * converts a uint8array to a word array.
   *
   * @param {string} u8str the uint8array.
   *
   * @return {wordarray} the word array.
   *
   * @static
   *
   * @example
   *
   * var wordarray = cryptojs.enc.u8array.parse(u8arr);
   */
  parse: function (u8arr) {
    // shortcut
    var len = u8arr.length
    // convert
    var words = []
    for (var i = 0; i < len; i++) {
      words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8)
    }
    return cryptojs.lib.wordarray.create(words, len)
  }
}
export default {
  u8array: cryptojs.enc.u8array
}

2、文件上传时加密

 // 上传文件
    handlefileupload(file) {
        this.upload.isuploading = true
        let reader = new filereader()
        reader.readasarraybuffer(file.file) // 以二进制数据读取文件
        reader.onload = () => {
          var filecontent =  new uint8array(reader.result) // 转成uint8array类型
          var encryptedcontent = encryptfile(filecontent); // 加密
          console.log(encryptedcontent, '加密后串');
          let blobtype = file.file.type
          let filename = file.file.name       
          let blob = this.atobtoblob(encryptedcontent, blobtype) // 将加密后串转blob
          let blobtofile = new file([blob], filename, {  
            type: blobtype,  
            lastmodified: date.now()  
          }); // 得到加密文件
          let formdata = new formdata();
          formdata.append("file", blobtofile); // 传给后端即可
          
        }
 
      
    },
    atobtoblob(intarray,type) {
      // 创建一个 blob 对象
      var blob = new blob([intarray], { type: type });
      return blob;
    }

3、解密并下载

 
// 解密逻辑 file-二进制-解密-blob-file
desfilelist() {
            this.files.map((item) => {
              let readers = new filereader()
              readers.readasarraybuffer(item.url) // item.url 为加密后的串
              readers.onload = () => {
                var filecontent = new uint8array(readers.result)
                // console.log(filecontent, 'filecontent加密前');
                var encryptedcontent = decryptfile(filecontent);
                console.log(encryptedcontent, '解密后3333');
                let blob = atobtoblob(encryptedcontent, item.url.type)
                console.log(blob,'blob');
                let blobtofile = new file([blob], item.url.name, {  
                  type: item.url.type,  
                  lastmodified: date.now()  
                })
                item.url = blobtofile
                  item.name = item.url.name
                item.tag=1
                // blobdownload(blob,blobtofile.name)
              }
            })
            console.log(this.files,'this.files');
            settimeout(() => {
                this.$refs.files.setfilelist(this.files)
            }, 500);
        },
 
 
export function blobdownload(blob, filename) {
  // 判断浏览器类型
  if (window.navigator && window.navigator.mssaveoropenblob) {
    // 如果是 ie 浏览器,使用 mssaveoropenblob 方法
    window.navigator.mssaveoropenblob(blob, filename);
  } else {
    var myurl = url.createobjecturl(blob); //创建图片的临时url
    // downloadfile(myurl,name)
    var a = document.createelement("a") //新建一个a链接
    a.setattribute("href", myurl) // a链接的url为图片的url
    a.setattribute("download", filename)
    a.setattribute("target", "_blank")
    let clickevent = document.createevent("mouseevents");
    clickevent.initevent("click", true, true);
    a.dispatchevent(clickevent);
  }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com