Mae*_*ros 5 node.js firebase google-cloud-functions axios pinata
我正在编写一个 Firebase 函数,该函数使用express. 当端点被调用时,它需要从外部API下载图像并使用该图像进行第二次API调用。第二个 API 调用需要将图像作为 readableStream. 具体来说,我正在调用Pinata APIpinFileToIPFS的端点。
我的 Firebase 功能用于axios下载图像并将fs图像写入/tmp. 然后我用来fs读取图像,将其转换为 areadableStream并将其发送到 Pinata。
我的代码的精简版本如下所示:
const functions = require("firebase-functions");
const express = require("express");
const axios = require("axios");
const fs = require('fs-extra')
require("dotenv").config();
const key = process.env.REACT_APP_PINATA_KEY;
const secret = process.env.REACT_APP_PINATA_SECRET;
const pinataSDK = require('@pinata/sdk');
const pinata = pinataSDK(key, secret);
const app = express();
const downloadFile = async (fileUrl, downloadFilePath) => {
try {
const response = await axios({
method: 'GET',
url: fileUrl,
responseType: 'stream',
});
// pipe the result stream into a file on disc
response.data.pipe(fs.createWriteStream(downloadFilePath, {flags:'w'}))
// return a promise and resolve when download finishes
return new Promise((resolve, reject) => {
response.data.on('end', () => {
resolve()
})
response.data.on('error', () => {
reject()
})
})
} catch (err) {
console.log('Failed to download image')
console.log(err);
throw new Error(err);
}
};
app.post('/pinata/pinFileToIPFS', cors(), async (req, res) => {
const id = req.query.id;
var url = '<URL of API endpoint to download the image>';
await fs.ensureDir('/tmp');
if (fs.existsSync('/tmp')) {
console.log('Folder: /tmp exists!')
} else {
console.log('Folder: /tmp does not exist!')
}
var filename = '/tmp/image-'+id+'.png';
downloadFile(url, filename);
if (fs.existsSync(filename)) {
console.log('File: ' + filename + ' exists!')
} else {
console.log('File: ' + filename + ' does not exist!')
}
var image = fs.createReadStream(filename);
const options = {
pinataOptions: {cidVersion: 1}
};
pinata.pinFileToIPFS(image, options).then((result) => {
console.log(JSON.stringify(result));
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Accept");
res.status(200).json(JSON.stringify(result));
res.send();
}).catch((err) => {
console.log('Failed to pin file');
console.log(err);
res.status(500).json(JSON.stringify(err));
res.send();
});
});
exports.api = functions.https.onRequest(app);
Run Code Online (Sandbox Code Playgroud)
有趣的是,我的调试消息告诉我该/tmp文件夹存在,但我下载的文件的文件在文件系统中不存在。
[Error: ENOENT: no such file or directory, open '/tmp/image-314502.png']。注意,当我手动访问图片的URL时,可以正确访问图片。
我尝试使用多种方法下载并保存文件,但都不起作用。另外,根据我所读到的内容,Firebase Functions 允许从/tmp.
任何建议将被认真考虑。请注意,我对 NodeJS 和 Firebase 非常陌生,所以请原谅我的基本代码。
非常感谢!
我无法看到您正在按照这篇文章中的建议初始化目录:
const bucket = gcs.bucket(object.bucket);
const filePath = object.name;
const fileName = filePath.split('/').pop();
const thumbFileName = 'thumb_' + fileName;
const workingDir = join(tmpdir(), `${object.name.split('/')[0]}/`);//new
const tmpFilePath = join(workingDir, fileName);
const tmpThumbPath = join(workingDir, thumbFileName);
await fs.ensureDir(workingDir);
Run Code Online (Sandbox Code Playgroud)
另外,请考虑,如果您使用两个函数,则该/tmp目录不会共享,因为每个函数都有自己的目录。这是Doug Stevenson 的解释。在同一个答案中,有一个关于本地和全局范围以及如何使用 tmp 目录的很好解释的视频:
Cloud Functions 仅允许在特定服务器实例中一次运行一个函数。并行运行的函数在不同的服务器实例上运行,这些实例具有不同的 /tmp 空间。每个函数调用都彼此完全隔离地运行。您应该始终清理在 /tmp 中写入的文件,以免它们累积并导致服务器实例随着时间的推移耗尽内存。
我建议使用通过 Cloud Functions 扩展的 Google Cloud Storage来实现您的目标。
| 归档时间: |
|
| 查看次数: |
604 次 |
| 最近记录: |