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

两台Node.js服务间传zip上传Express(multer)后损坏问题求助

问题根因

  • zipDirectory 是异步操作,调用后未等待压缩完成就直接读取zip文件,此时压缩包还未完全写入磁盘,读取到的是残缺文件,这是压缩包损坏的核心原因。
  • 代码逻辑冗余:使用了fs.readFile读取文件内容,但实际未用到读取结果,反而又创建了createReadStream,无实际意义。
  • axios的then回调参数写反:then第一个入参是成功响应对象,第二个才是错误对象,原逻辑会导致上传成功时也抛出错误,触发后续文件删除逻辑,导致本地原始压缩包被提前删掉,所以本地打开也会报错。
  • 服务端2的上传接口未返回任何响应,axios请求会超时抛错,同样会触发错误逻辑,导致本地文件被误删。
  • 扩展名提取逻辑存在缺陷:如果原始文件名包含多个.(比如backup.v2.zip),按split('.')[1]取到的不是zip后缀,会导致保存的文件扩展名错误,无法正常识别为压缩包。
  • 原代码中使用unlinkSync删除目录是错误的,unlinkSync仅能删除文件,删除目录需要用支持递归的方法。

修复代码

服务端1代码

// 等待zip压缩完成,若zipDirectory为callback形式,先包装为Promise
await new Promise((resolve, reject) => {
  zipDirectory(
    `C:/Users/${config.usuario}/Backup/`,
    `C:/Users/${config.usuario}/backup.zip`,
    (err) => err ? reject(err) : resolve()
  );
});
const nbackup = uuidv4();
const form = new FormData();
// 直接追加文件流,不需要提前readFile
form.append("arquivo", fs.createReadStream(`C:/Users/${config.usuario}/backup.zip`));
try {
  const res = await axios.post(
    `${config.api}/backup?chave=${process.env.CHAVE}&vps=${config.vps}&id=${nbackup}`,
    form,
    {
      headers: {
        ...form.getHeaders()
      }
    }
  );
  if (res.status === 200) {
    fs.unlinkSync(`C:/Users/${config.usuario}/backup.zip`);
    // 使用rmSync递归删除目录
    fs.rmSync(`C:/Users/${config.usuario}/Backup`, { recursive: true, force: true });
  }
} catch (err) {
  console.log('上传失败', err);
}

服务端2代码

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "uploads/");
  },
  filename: function (req, file, cb) {
    // 正确提取扩展名,取最后一个.后的内容
    const extensaoArquivo = file.originalname.split('.').pop();
    const novoNomeArquivo = require("crypto").randomBytes(64).toString("hex");
    cb(null, `${novoNomeArquivo}.${extensaoArquivo}`);
  }
});

const upload = multer({ storage: storage });

app.post("/api/backup", upload.single("arquivo"), (req, res) => {
  console.log("文件接收完成");
  // 返回响应避免axios超时
  res.status(200).send({ status: 'success' });
});

额外优化建议

  • 上传前先计算本地zip文件的MD5值,上传完成后服务端也计算接收文件的MD5,两者一致再确认上传成功,避免传输过程中损坏。
  • 不要在上传流程中直接删除本地原始文件,可以添加错误重试逻辑,多次失败后再告警处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:54:01