【发布时间】:2020-12-12 01:04:40
【问题描述】:
我是 node.js 和一般后端的新手,并试图为我的宠物项目提供下载文件的 API。为此,我决定在 Firebase 存储中托管文件,并通过 Firebase Functions 提供对它们的访问。为此,我使用以下代码:
const app = express()
app.get('/:filename', async (request, response) => {
const file = await admin.storage().bucket().getFiles({
autoPaginate: false,
delimiter: '/',
prefix: 'files/'
})
.then(response => {
const files = response[0]
files.shift()
return files[0] //let's take first file for example
})
response.attachment(`${filename}.zip`);
response.setHeader('Content-Type', `${file.metadata.type}`) // application/zip
response.setHeader('Content-Length', file.metadata.size)
file.createReadStream()
.pipe(response)
})
exports.styles = functions.https.onRequest(app)
就下载文件的能力而言,当从浏览器访问 URL 并在下载后打开它时,一切正常,所以这里没有问题。
让我烦恼的是,在提供文件和下载完成后,功能并没有结束。相反,它会在模拟器上引发超时错误(尚未部署此功能,因此无法确定它是否可以在现场重现)。
⚠ functions: Your function timed out after ~60s. To configure this timeout, see
https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.
> /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:642
> throw new Error("Function timed out.");
> ^
>
> Error: Function timed out.
> at Timeout._onTimeout (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:642:23)
> at listOnTimeout (internal/timers.js:551:17)
> at processTimers (internal/timers.js:494:7)
我也试过以下sn-p,但结果是一样的:
file.createReadStream()
.on('end', () => {
console.log("end reading file stream. closing connection")
response.end(() => console.log("connection closed"))
})
.pipe(response)
此外,第一个和第二个日志语句都不会打印。 有趣的是,部署脚本时不会重现此问题,仅在模拟器上发生。
我对此做了一些研究,发现在流期间触发了一些事件,可以处理并做response.end(),但显然在管道时不需要这样做。
我现在被困住了,因此感谢您的帮助。
【问题讨论】:
-
作为最佳实践,您必须在 .then() 之后使用 .catch() 处理 Cloud Functions 中的错误,以更好地管理和解决 errors。另外请按照以下答案正确结束您的云功能。
标签: node.js typescript firebase google-cloud-functions firebase-storage