首页 > 解决方案 > 从云功能流式传输 zip 下载

问题描述

我有一个 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'); 
}

标签: node.jsfirebaseexpressgoogle-cloud-functions

解决方案


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

如果您打算表示您正在发送成功的响应,只需output.status(200)按照您对 404 错误所做的相同方式说出来。在前面做。当您通过管道发送响应时,您无需执行任何操作即可最终关闭响应。管道完成后,响应将自动刷新并最终确定。只有当您想提早退出而不发送任何响应时,您才应该调用end() 。

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


推荐阅读