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

Cloud Function下载URL后上传Cloud Storage文件为空问题

解决Cloud Function中下载文件后上传至Cloud Storage为空的问题

你遇到的核心问题是异步操作没有正确等待执行完成,导致上传文件的时候,下载操作还没完成,所以/tmp里的文件是空的,上传后自然只有20B的空文件。而且你日志里的file downloaded其实是在下载开始前就打印了,根本不是下载完成的标志。

先给你修正后的完整可运行代码:

const { Storage } = require('@google-cloud/storage');
const http = require('http');
const fs = require('fs');
const { promisify } = require('util');
const pipeline = promisify(require('stream').pipeline);

exports.writeToBucket = async (req, res) => {
  try {
    const fileStream = fs.createWriteStream("/tmp/pp-monthly-update.txt");
    const downloadUrl = "http://prod.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-monthly-update.txt";

    // 把http.get的回调式操作包装成Promise,等待下载完成
    await new Promise((resolve, reject) => {
      const request = http.get(downloadUrl, (response) => {
        // 使用stream.pipeline处理流,比直接pipe更可靠,能处理错误
        pipeline(response, fileStream)
          .then(resolve)
          .catch(reject);
      });

      request.on('error', reject);
    });

    console.log('file downloaded');

    // 初始化Storage客户端(只需要初始化一次)
    const storage = new Storage();
    const bucketName = 'landregistry_pricepaid_month';
    const filename = '/tmp/pp-monthly-update.txt';

    // 等待上传操作完成
    await storage.bucket(bucketName).upload(filename, {
      gzip: true,
      metadata: {
        cacheControl: 'no-cache',
      },
    });

    res.status(200).send(`${filename} uploaded to ${bucketName}.`);
  } catch (err) {
    console.error('操作出错:', err);
    res.status(500).send('操作失败,请查看日志');
  }
};

关键改进点说明:

  • 改用async/await处理异步流程:把导出的函数声明为async,这样可以用await等待所有异步操作完成,避免"先上传后下载"的顺序错误。
  • 包装http.get为Promise:原生http.get是基于回调的,我们把它包装成Promise,确保只有当文件完全下载写入到/tmp后,才会执行后续的上传操作。
  • 使用stream.pipeline替代直接pipe:pipeline是Node.js官方推荐的流处理方式,它能更好地处理流的错误、自动清理资源,比直接用response.pipe(file)更可靠。
  • 移除重复的模块导入:你之前在函数内部重复导入了Storage,把它移到顶部只导入一次即可。
  • 添加错误捕获:用try/catch包裹所有操作,一旦出错可以返回500状态码并打印错误日志,方便排查问题。

为什么之前的代码会出现空文件?

你原来的代码里,http.get和storage.upload都是异步操作,代码会直接跳过它们继续执行res.status(200).send(...),这时候文件还在下载过程中,甚至可能还没写入任何内容,上传的自然是空文件。日志里的file downloaded也是在下载请求刚发起就打印了,不是真的下载完成。

现在修正后的代码会严格等待下载完成→打印日志→等待上传完成→返回响应,这样就能保证上传的是完整的文件了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 20:47:52