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

Google Cloud Storage上传完成后返回undefined问题修复求助

问题原因

你的uploadFile函数虽然声明为async,但内部没有返回一个能捕获流操作结果的Promise。流的finish事件回调里的返回值不会被外层函数接收,导致调用await uploadFile(...)时拿到的是undefined。另外路由里的文件缺失判断没有终止后续逻辑,可能引发重复响应的错误。

修改后的代码

处理上传的独立文件

import { Storage } from '@google-cloud/storage';

const UPLOAD_BUCKET: string = process.env.GCS_BASE_BUCKET || '';

async function uploadFile(file: any, fileName: string, targetFolder: string) {
  return new Promise((resolve, reject) => {
    const destinationFilepath: string = `${targetFolder ? targetFolder + '/' : ''}${fileName}`;
    const storage = new Storage();
    const options = {
      destination: destinationFilepath,
      metadata: {
        contentType: file.mimetype,
      },
    };
    const bucket = storage.bucket(UPLOAD_BUCKET);
    const blob = bucket.file(destinationFilepath);
    const blobStream = blob.createWriteStream(options);

    blobStream.on('error', (err: Error) => {
      console.error('上传失败:', err);
      reject(err);
    });

    blobStream.on('finish', async () => {
      try {
        await blob.makePublic();
        const result = {
          message: `Success! File uploaded to ${blob.publicUrl}`,
          publicUrl: blob.publicUrl,
          bucket: bucket.name,
          fileName: blob.name
        };
        resolve(result);
      } catch (e) {
        console.error('设置文件公开失败:', e);
        reject(e);
      }
    });

    blobStream.end(file.buffer);
  });
}

export { uploadFile };

路由文件index.ts

app.post('/gcs/upload/:folder?', multer.single('file'), async (req: Request, res: Response) => {
  const folder: string = req.params.folder || '';
  const fileName: string = req?.file?.originalname || 'FileWithoutFileName.txt';
  
  if (!req.file) {
    return res.status(400).send('Missing File');
  }

  try {
    const uploadResult = await uploadFile(req.file, fileName, folder);
    res.status(200).send(uploadResult);
  } catch (err) {
    res.status(500).send(`上传出错: ${(err as Error).message}`);
  }
});

修改说明

  1. 用Promise包裹流操作:把整个上传流程封装在Promise中,通过resolve返回成功结果,reject抛出错误,确保await能正确捕获返回值。
  2. 完善错误链路:流的错误、设置文件公开权限的错误都通过reject抛出,路由层用try/catch统一捕获并返回500状态码。
  3. 修复路由逻辑:文件缺失判断后添加return终止后续代码执行,避免重复发送响应;将原401状态码改为400(401用于身份验证失败,文件缺失属于请求参数错误,符合HTTP规范)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:33:00