Node.js 在emulator上从Firebase存储流式传输文件时Firebase函数超时

Node.js 在emulator上从Firebase存储流式传输文件时Firebase函数超时,node.js,typescript,firebase,google-cloud-functions,firebase-storage,Node.js,Typescript,Firebase,Google Cloud Functions,Firebase Storage,我不熟悉node.js和后端,我尝试为我的宠物项目提供一个下载文件的API。为此,我决定将文件托管在Firebase存储中,并通过Firebase函数提供对它们的访问。为了实现这一点,我使用以下代码: const-app=express() app.get('/:filename',异步(请求、响应)=>{ const file=wait admin.storage().bucket().getFiles({ 自动搅拌:错误, 分隔符:“/”, 前缀:“文件/” }) 。然后(响应=>{ 常量文

我不熟悉node.js和后端,我尝试为我的宠物项目提供一个下载文件的API。为此,我决定将文件托管在Firebase存储中,并通过Firebase函数提供对它们的访问。为了实现这一点,我使用以下代码:

const-app=express()
app.get('/:filename',异步(请求、响应)=>{
const file=wait admin.storage().bucket().getFiles({
自动搅拌:错误,
分隔符:“/”,
前缀:“文件/”
})
。然后(响应=>{
常量文件=响应[0]
file.shift()文件
返回文件[0]//以第一个文件为例
})
附件(`${filename}.zip`);
response.setHeader('Content-Type',`${file.metadata.Type}`)//application/zip
response.setHeader('Content-Length',file.metadata.size)
createReadStream()文件
.管道(响应)
})
exports.styles=functions.https.onRequest(应用程序)
就下载文件的能力而言,当从浏览器访问URL并在下载后打开它时,所有功能都可以正常工作,因此这里没有问题

让我感到困扰的是,在提供文件并完成下载后,函数并没有结束。相反,它会在emulator上抛出一个超时错误(还没有部署它,所以不能确定它是否可以在live上重现)

我还尝试了以下代码段,但结果相同:

file.createReadStream()
.on('end',()=>{
console.log(“结束读取文件流。关闭连接”)
response.end(()=>console.log(“连接已关闭”))
})
.管道(响应)
此外,既不打印第一个日志语句,也不打印第二个日志语句。 有趣的是,在部署脚本时不会再现此问题,这只发生在模拟器上

我对此做了一些研究,发现在流期间会触发一些事件,可以对这些事件进行处理并执行
response.end()
,但显然在管道中不需要这样做

我现在陷入困境,因此非常感谢您的帮助。

我们必须确保功能正确终止的状态:

使用res.redirect()、res.send()或res.end()终止HTTP函数

因此,请检查createReadStream何时“结束”,然后调用response的end()函数

file.createReadStream()
  .on('end', function() {
    response.end();
  })
  .pipe(response);

尝试使用以下设置函数中的超时:

const runtimeOpts = {
  timeoutSeconds: 300
}

exports.styles = functions.runWith(runtimeOpts).https.onRequest(app)

timeoutSeconds的最大值为540或9分钟

作为最佳实践,您必须在.then()之后使用.catch()处理云函数中的错误,以更好地管理和解决问题。另外,请按照下面的回答正确结束您的云功能。谢谢您的回答。我确实试过这个,但这个不起作用。我仍然收到超时错误。我将更新OP以包含此详细信息。顺便说一句,我在OP中提到,在我的研究中,我偶然发现一篇帖子说,当管道连接到
响应时,不需要手动关闭。它是针对具体的节点版本还是一般的节点版本?可以尝试的其他方法是
returnresponse.end()您实际上可以返回整个内容<代码>返回文件.createReadStream().on(…)
const runtimeOpts = {
  timeoutSeconds: 300
}

exports.styles = functions.runWith(runtimeOpts).https.onRequest(app)