【问题标题】:Streaming a zip download from cloud functions从云功能流式传输 zip 下载
【发布时间】:2019-01-26 18:47:21
【问题描述】:

我有一个 firebase 云功能,它使用 express 将图像的 zip 文件流式传输到客户端。当我在本地测试云功能时,它工作正常。当我上传到 Firebase 时,我收到此错误:

错误:发送后无法设置标头。

什么可能导致此错误?内存限制?

export const zipFiles = async(name, params, response) => {


  const zip = archiver('zip', {zlib: { level: 9 }});


  const [files] = await storage.bucket(bucketName).getFiles({prefix:`${params.agent}/${params.id}/deliverables`});

  if(files.length){
    response.attachment(`${name}.zip`);
    response.setHeader('Content-Type', 'application/zip');
    response.setHeader('Access-Control-Allow-Origin', '*')

    zip.pipe(output);

    response.on('close', function() { 
      return output.send('OK').end(); // <--this is the line that fails
  });

  files.forEach((file, i) => {

    const reader = storage.bucket(bucketName).file(file.name).createReadStream();
    zip.append(reader, {name: `${name}-${i+1}.jpg`});

  });
  zip.finalize();
}else{
  output.status(404).send('Not Found'); 
}

【问题讨论】:

  • 该错误消息的意思是字面上的意思:您的代码在它已经完成之后尝试发送标头。我希望它是send('OK'),因为这可能会强制输出流的主体变为文本,其中 zip 文件将作为二进制文件发送。
  • 删除'send('ok')'。会不会有什么不良影响?
  • 我无法为您回答这个问题,因为这取决于接收 zip 的客户端。但是我能很快想到的客户端在接收二进制文件时不会在正文中寻找OK 字符串。这当然值得一试,然后看看:1) 文件现在是否已发送给您的客户,2) 客户是否按照您希望的方式处理它。

标签: node.js firebase express google-cloud-functions


【解决方案1】:

弗兰克在 cmets 中所说的是真的。在开始发送任何内容正文之前,您需要确定所有标头,包括 HTTP 状态响应。

如果您打算表示您正在发送成功的响应,只需像处理 404 错误一样说 output.status(200)。在前面做。当您通过管道发送响应时,您无需执行任何操作即可最终关闭响应。管道完成后,响应将自动刷新并最终确定。只有当您想提早退出而不发送任何回复时,您才应该致电end()

请记住,Cloud Functions 仅支持 10MB (read more about limits) 的最大有效负载,因此如果您尝试压缩超过该总数,它将无法正常工作。事实上,根本没有“流式传输”或分块响应。整个有效载荷都在内存中构建并作为一个单元传输出去。

【讨论】:

  • 哎呀,废话。我正在尝试构建〜100MB 的拉链。对于如何解决这个问题,您可以提出任何替代方案吗?
  • 将压缩包写回存储,给他们一个直接的 URL,并安排稍后将其删除。
猜你喜欢
  • 2017-07-23
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多