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

Node.js项目在Render免费账户上传大文件至Google Drive内存不足问题咨询

解决Render免费账户Node.js上传大文件到Google Drive内存溢出问题

问题原因

当前代码使用multer.single()会将整个文件加载到内存中,399MB的视频文件加上Node.js运行时本身的内存占用,直接超过了Render免费账户512MB的内存限制,导致内存溢出报错。

解决方法

核心思路是避免将整个文件加载到内存,改用磁盘存储临时文件,并通过Google Drive的可恢复上传(Resumable Upload)流式传输文件。

1. 修改Multer配置为磁盘存储

替换原有的multer.single(),改用磁盘存储临时文件,避免内存占用过高:

const multer = require('multer');
const fs = require('fs');
const path = require('path');

// 确保临时目录存在,不存在则创建
const tmpDir = './tmp/uploads';
if (!fs.existsSync(tmpDir)) {
  fs.mkdirSync(tmpDir, { recursive: true });
}

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, tmpDir);
  },
  filename: (req, file, cb) => {
    // 添加时间戳避免文件名重复
    cb(null, `${Date.now()}-${file.originalname}`);
  }
});

const upload = multer({ 
  storage: storage,
  limits: { fileSize: 500 * 1024 * 1024 } // 限制最大文件大小,比如500MB
});

2. 改用Google Drive可恢复上传(流式传输)

修改uploadToGoogleDrive函数,直接读取磁盘文件流进行分片上传,无需将整个文件加载到内存:

const uploadToGoogleDrive = async (file, fid, auth) => {
  const idx = file.originalname.lastIndexOf('.');
  const ext = idx === -1 ? '' : file.originalname.substring(idx);
  const fileMetadata = {
    name: `file${fid}${ext}`,
    parents: [googleFolderId],
  };

  const drive = google.drive({ version: "v3", auth });

  // 初始化可恢复上传会话
  const resumableSession = await drive.files.create({
    requestBody: fileMetadata,
    media: {
      mimeType: file.mimetype,
      body: fs.createReadStream(file.path) // 流式读取磁盘文件,不占内存
    },
    fields: "id, webViewLink",
    uploadType: 'resumable'
  });

  // 执行上传并等待完成
  const uploadResponse = await new Promise((resolve, reject) => {
    drive.files.create({
      uploadType: 'resumable',
      resumable: resumableSession.resumable
    }, (err, res) => {
      if (err) reject(err);
      else resolve(res);
    });
  });

  // 设置公共读取权限
  await drive.permissions.create({
    fileId: uploadResponse.data.id,
    requestBody: {
      role: 'reader',
      type: 'anyone',
    }
  });

  // 上传完成后删除临时文件,释放磁盘空间
  fs.unlinkSync(file.path);

  return uploadResponse.data.webViewLink;
};

3. 更新路由中间件

将原路由中的multer.single("file")替换为我们配置好的upload.single("file"):

app.post("/upload-file-to-google-drive2", upload.single("file"), async (req, res, next) => {
  if (!req.file) {
    res.status(400).send({ error: "No file uploaded." });
    return;
  }
  const auth = authenticateGoogle();
  const response = await uploadToGoogleDrive(req.file, req.body.id, auth);
  res.status(200).json({ response });
});

额外优化建议

  • 添加定时任务清理超过24小时的临时文件,避免Render免费账户磁盘空间耗尽
  • 给上传流程添加异常捕获,确保上传失败时临时文件也能被删除
  • 监控Render账户的磁盘和内存使用情况,及时调整临时文件策略

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:53:11