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

Node.js下API返回PDF上传GCS后无法打开的问题求助

解决GCS上传PDF后无法打开的问题

核心问题分析

你的代码存在重复写入数据的错误:

stream.write(new Buffer.from(data, 'binary'));
// ...
stream.end(Buffer.from(data, 'binary'));

stream.write和stream.end都写入了同一数据,导致最终上传到GCS的PDF文件内容是原内容的两倍,文件结构被破坏,因此无法正常打开。

另外需要确认API返回的response数据类型:如果是HTTP响应对象(比如axios/fetch返回的响应),直接传递response可能不是原始二进制数据,需要正确提取二进制内容。

修复方案

方案1:修正重复写入问题(基础修复)

去掉多余的stream.write调用,只在stream.end中写入一次数据:

const { Storage } = require('@google-cloud/storage')

async uploadFileToGCS(id, pdfData) {
    const storage = new Storage();
    const bucket = storage.bucket('<bucket name>');
    const fileSuffix = 'pdf';
    const getBucketFile = fileName => bucket.file(`${fileName}.${fileSuffix}`);

    const upload = data =>
      new Promise((resolve, reject) => {
        const uuid = `${id}`;
        const file = getBucketFile(uuid);
        const stream = file.createWriteStream({
          metadata: {
            'Content-Type': 'application/pdf',
            'Content-Disposition': `attachment; filename=${uuid}.pdf`,
          },
          resumable: false,
        });
        
        stream.on('error', err => {
          reject(err);
        });

        stream.on('finish', () => {
          resolve(uuid);
        });

        // 只写入一次数据
        stream.end(Buffer.from(data, 'binary'));
      });

    await upload(pdfData);
  },

方案2:直接使用流传输(更高效,推荐)

如果API返回的是可读流(比如fetch的response.body或axios返回的流),可以直接通过管道(pipe)传输到GCS的写入流,避免手动处理Buffer:

const { Storage } = require('@google-cloud/storage')

async uploadFileToGCS(id, pdfStream) {
    const storage = new Storage();
    const bucket = storage.bucket('<bucket name>');
    const fileSuffix = 'pdf';
    const uuid = `${id}`;
    const file = bucket.file(`${uuid}.${fileSuffix}`);

    return new Promise((resolve, reject) => {
      pdfStream.pipe(file.createWriteStream({
        metadata: {
          'Content-Type': 'application/pdf',
          'Content-Disposition': `attachment; filename=${uuid}.pdf`,
        },
        resumable: false,
      }))
      .on('error', reject)
      .on('finish', () => resolve(uuid));
    });
  },

调用时直接传入API返回的流即可,例如使用fetch的场景:

const apiResponse = await fetch('你的PDF API地址');
await uploadFileToGCS(id, apiResponse.body);

方案3:确保获取正确的二进制数据

如果使用axios调用API,需要设置responseType: 'arraybuffer'来获取原始二进制数据,避免默认的字符串解析破坏PDF内容:

const axios = require('axios');

// 调用API获取PDF
const apiResponse = await axios.get('你的PDF API地址', {
  responseType: 'arraybuffer'
});

// 上传到GCS
await uploadFileToGCS(id, apiResponse.data);

验证步骤

  1. 修复代码后重新上传文件到GCS
  2. 下载文件后,检查文件大小是否和API返回的原始PDF大小一致
  3. 用PDF阅读器打开文件,确认内容正常

内容的提问来源于stack exchange,提问作者M. Fadli Bayu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:01:36