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

使用Node.js向Google Cloud Storage上传1GB+大文件遇错求助

解决大文件(1GB+)上传失败的方案

核心问题分析

你已经设置了express的请求体大小限制:

app.use(express.json({ limit: "5000mb" }));
app.use(express.urlencoded({ extended: true, limit: "5000mb" }));

但当前使用multer.memoryStorage()会把整个文件加载到服务器内存中,1GB+的文件不仅会耗尽内存,还会导致HTTP请求超时(4-5分钟已超过很多服务器/客户端的默认超时阈值),最终触发"Fail to fetch"错误。multer的存储方式和超时配置才是关键瓶颈。

具体修复步骤

1. 替换multer存储策略,避免内存过载

放弃memoryStorage,改用diskStorage临时存储文件,同时配置multer的文件大小限制:

const multer = require('multer');
// 使用磁盘存储临时文件,避免内存占用
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './temp/uploads'); // 确保这个目录存在,可自行修改路径
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname);
  }
});

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 5000 * 1024 * 1024 // 5GB限制,和你的express配置匹配
  }
});

2. 流式上传到Google Cloud Storage(GCS)

不再将整个文件读入内存,而是直接把临时文件的流 pipe 到GCS的写入流,减少内存占用并提升上传效率:

const fs = require('fs');
const { format } = require('util');

app.post("/api/upload/", upload.single("file"), async function (req, res, next) {
  try {
    if (!req.file) {
      return res.status(400).json({
        success: false,
        message: "File is not sent"
      });
    }

    const blob = bucket.file(req.file.originalname);
    const blobStream = blob.createWriteStream({
      gzip: true,
      resumable: true,
      contentType: req.file.mimetype // 自动获取文件MIME类型,比硬编码更可靠
    });

    // 读取临时文件流并pipe到GCS
    const fileStream = fs.createReadStream(req.file.path);
    
    fileStream.on('error', (err) => {
      console.error('临时文件读取错误:', err);
      next(err);
    });

    blobStream.on("error", (err) => {
      console.error('GCS上传错误:', err.message, err.name);
      next(err);
    });

    blobStream.on("finish", async () => {
      // 上传完成后删除临时文件
      fs.unlinkSync(req.file.path);

      const publicUrl = format(
        `https://storage.googleapis.com/${bucket.name}/${blob.name}`
      );
       
      res.status(201).json({
        success: true,
        message: "Upload success",
        url: publicUrl // 可选返回文件访问URL
      });
    });

    // 开始流式传输
    fileStream.pipe(blobStream);
  } catch (error) {
    console.error('上传流程错误:', error);
    return res.status(500).json({
      success: false,
      message: error.message
    });
  }
});

3. 调整服务器超时设置

Express默认的请求超时可能不足以处理大文件上传,需要延长超时时间:

// 在app初始化后设置全局超时
app.use((req, res, next) => {
  req.setTimeout(3600000); // 1小时超时,根据实际需求调整
  res.setTimeout(3600000);
  next();
});

// 如果使用Node.js原生HTTP服务器,同步设置超时
const http = require('http');
const server = http.createServer(app);
server.timeout = 3600000; // 1小时

4. 客户端侧调整(关键)

"Fail to fetch"也可能来自客户端的超时限制,比如使用封装请求库时需手动设置超时:

// 示例:axios上传配置
axios.post('/api/upload/', formData, {
  timeout: 3600000, // 1小时超时
  headers: {
    'Content-Type': 'multipart/form-data'
  }
});

进阶优化:GCS可恢复上传

对于10GB+的超大文件,推荐使用GCS的可恢复上传功能,支持断点续传,即使上传中断也能从断点继续。可通过@google-cloud/storage库的createResumableUpload方法实现。

内容的提问来源于stack exchange,提问作者Siyam Uddin Talha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:50:11