You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Crypto.js AES算法加密文件后上传服务器失败问题咨询

问题原因
  • 异步执行顺序错误:FileReader.readAsDataURL()是异步API,调用后不会立刻触发onload回调,你在调用读取方法后直接发起fetch请求,此时加密、append到formData的逻辑都还没执行,formData为空所以服务器收不到文件。
  • 事件绑定逻辑错误:form的submit事件绑定被放在了文件选择框的change回调中,每次选择符合格式的文件都会新增一次submit监听,后续提交表单会触发多次重复请求。
  • 加密逻辑异常:CryptoJS.AES.encrypt()返回的是CipherParams对象而非字符串,直接传入File构造器会导致内容序列化错误;同时readAsDataURL读取的内容是带前缀的Base64 Data URI,不是文件原始二进制内容,加密后体积更大,也不利于后续解密还原。
解决方案

修正后完整代码

// 全局变量/常量声明
const url = 'process.php';
const form = document.querySelector('form');
const fileInput = document.querySelector("#inputGroupFile01");
const ALLOWED_EXT = /(.*?)\.(jpg|gif|doc|pdf|mp3|mp4|avi|txt|png|jpeg|tif)$/;
const ENCRYPT_KEY = "ThisIsPasswordForTheFile";

// 表单提交事件绑定 移到外层避免重复绑定
form.addEventListener('submit', (e) => {
  e.preventDefault();
  const file = fileInput.files[0];
  if (!file) {
    alert("请先选择文件");
    return;
  }
  // 校验文件格式
  if (!file.name.match(ALLOWED_EXT)) {
    alert("请选择符合要求的文件格式");
    return;
  }

  const formData = new FormData();
  const reader = new FileReader();

  reader.onload = function() {
    // 加密后把CipherParams转成字符串再封装成File
    const encrypted = CryptoJS.AES.encrypt(reader.result, ENCRYPT_KEY).toString();
    // 可以保留原文件名加.encrypted后缀 方便后续解密识别
    const encryptedFile = new File([encrypted], `${file.name}.encrypted`, {
      type: "text/plain"
    });
    formData.append('files', encryptedFile);

    // 加密完成、append到formData后再发起请求
    fetch(url, {
      method: 'POST',
      body: formData,
    }).then((response) => {
      console.log("上传成功");
    }).catch(err => {
      console.error("上传失败", err);
    });
  }

  // 如果需要加密原始二进制 可以用readAsArrayBuffer 再转成CryptoJS支持的WordArray
  // 这里保留你原来的readAsDataURL写法 如需修改可以自行调整
  reader.readAsDataURL(file);
});

补充说明

  1. 服务器端PHP接收逻辑需要正常处理$_FILES['files'],同时确保上传目录有可写权限,否则即使收到文件也无法写入目录。
  2. 如果你需要加密文件原始二进制内容,可将readAsDataURL改为readAsArrayBuffer,再通过CryptoJS.lib.WordArray.create(arrayBuffer)转换格式后再加密,体积更小更高效。
  3. 解密时需要先读取加密后的字符串,用CryptoJS.AES.decrypt(加密字符串, ENCRYPT_KEY).toString(CryptoJS.enc.Utf8)拿到原始Data URI,再去掉前缀转成对应文件格式即可还原。

内容的提问来源于stack exchange,提问作者Svitlana Kuievda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 05:06:03