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

通过Google Cloud Function上传文件至GCS后文件为空问题排查

问题描述

我尝试通过Google Cloud Function处理HTTP POST请求的文件上传,并将文件存储到Google Cloud Storage存储桶中。文件看似上传成功,控制台显示正确的文件大小,但查看时文件损坏,下载后文件大小为0字节。

我的Google Cloud Function代码如下:

const packageObj = require('./package.json');
const functions = require('@google-cloud/functions-framework');
const { Storage } = require('@google-cloud/storage');
const storage = new Storage();

functions.http('main', (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  if (req.method === 'OPTIONS') {
    res.set('Access-Control-Allow-Methods', 'GET');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
  } else if (req.method === 'POST') {
    const file = req.body;
    const bucketName = 'MY_BUCKET_NAME';
    const bucket = storage.bucket(bucketName);
    const f = storage.bucket(bucketName).file('test.jpg');
    f.save(file).then(() => {
      res.set('Content-Type', 'application/json');
      res.status(200).send(JSON.stringify(
        {
          version: packageObj.version,
          message: 'File uploaded!'
        },
        null,
        2
      ));
    });
  }
});

我使用functions-framework,运行命令:

functions-framework --target=main

然后执行:

curl -F 'data=@test/resources/car_image.jpg' http://localhost:8080/main

(我也部署了函数进行测试,排除functions-framework的问题,但结果相同。)

在控制台中,文件大小显示为62.9KB,与我上传的测试图片大小一致,但下载后文件大小为0字节,且预览损坏。

解决方案

问题根源及修复点如下:

  • 未解析multipart表单数据:curl -F发送的是multipart/form-data格式,直接读取req.body无法获取正确的文件二进制内容,需用multer中间件处理。
  • CORS配置错误:OPTIONS请求中允许的方法仅为GET,但实际使用POST,需修正允许的请求方法。
  • 文件保存对象错误:直接保存req.body会存储解析后的表单对象,而非文件二进制数据。

步骤1:安装依赖

npm install multer

步骤2:修改函数代码

const packageObj = require('./package.json');
const functions = require('@google-cloud/functions-framework');
const { Storage } = require('@google-cloud/storage');
const multer = require('multer');
const storage = new Storage();
// 配置multer使用内存存储,临时保存文件缓冲区
const upload = multer({ storage: multer.memoryStorage() });

// 用multer中间件解析名为'data'的表单字段(对应curl中的字段名)
functions.http('main', upload.single('data'), (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  
  if (req.method === 'OPTIONS') {
    // 修正CORS配置,允许POST和OPTIONS方法
    res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    return res.status(204).send('');
  }

  if (req.method !== 'POST') {
    return res.status(405).send('Method Not Allowed');
  }

  // 校验文件是否存在
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }

  const bucketName = 'MY_BUCKET_NAME';
  const file = storage.bucket(bucketName).file('test.jpg');

  // 上传文件缓冲区到GCS,同时指定文件类型
  file.save(req.file.buffer, {
    contentType: req.file.mimetype,
    resumable: false
  })
  .then(() => {
    res.set('Content-Type', 'application/json');
    res.status(200).json({
      version: packageObj.version,
      message: 'File uploaded!'
    });
  })
  .catch(err => {
    console.error('Upload error:', err);
    res.status(500).json({ error: 'File upload failed' });
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:45:20