因此,根据 Donnald Cucharo 的回答,我将为像我这样仍在使用 javascript 引擎(不支持方法签名中的异步)而不是 typescript 引擎的人发布我的工作解决方案:
步骤 1)
在您的项目中安装@google-cloud/storage npm,据我了解,每个 Firebase 存储都构建在谷歌云存储实例之上。
第 2 步)按照 this guide 从您的 firebase 项目控制台生成一个管理员密钥,以便将其上传到您的函数文件夹中,以授权您的函数项目与您的存储项目进行身份验证和通信。
第 3 步)使用以下代码(它与 Donnald Cucharo 的解决方案非常相似,但大量使用了 Promise):
const functions = require("firebase-functions");
const path = require("path");
const os = require("os");
class System {
...
/**
* Extract th extension of a file from it's path, and returns it.
* @param {String} directory [Dir from where to extract the extension from.]
* @return {String} [Containing the extension of the file from the directory or undefined]
*/
getFileExtensionFromDirectory(directory) {
const ext = path.extname(directory);
if (ext === "") {
return undefined;
}
return ext;
}
/**
* Extract the name of the file from a directory.
* @param {String} directory [Dir from where to extract the extension from.]
* @return {String} [Containing the filename]
*/
getFileNameFromDirectory(directory) {
const extension = this.getFileExtensionFromDirectory(directory);
if (extension === undefined) return extension;
return path.basename(directory, extension);
}
/**
* Returns the system temp directory.
* @return {String} [Containing the system temporary directory.]
*/
getSystemTemporarydirectory() {
return os.tmpdir();
}
}
module.exports = System;
然后,是时候实际上传文件了:
const admin = require("firebase-admin");
const functions = require("firebase-functions");
const bucket = admin.storage().bucket(functions.config().bucket.url);
const System = require("../System/System");
const fs = require("fs");
/**
* Pure fabrication class to access the Firebase services
*/
class Firebase {
/**
* Create a new file in the storage.
* @param {Object} wrapper [File to upload in the storage.]
* @param {String} path [Path to upload file to.]
* @return {object} [Containing the response]
*/
postStorageFileAsync(wrapper) {
return new Promise((res, rej)=>{
if (wrapper.file === undefined) {
return rej({code: 400, error:
{it: "Devi forninre il valore in base64 del file che vuoi caricare.",
en: "You must provide the base64 value of the file to upload."}});
}
if (wrapper.path === undefined) {
return rej({code: 400, error:
{it: "Devi fornire il percorso dove vuoi caricare il tuo file.",
en: "Missing path filed in wrapper."}});
}
const fileName = System.prototype.getFileNameFromDirectory(wrapper.path);
const fileExtension = System.prototype.getFileExtensionFromDirectory(wrapper.path);
if (fileName === undefined || fileExtension === undefined) {
return rej({code: 400, error:
{it: "Formato del file non riconosciuto.",
en: "Unrecognized file type or file name, the file should be in fileName.extension format"}});
}
const file = fileName + fileExtension;
const tmpDirectory = System.prototype.getSystemTemporarydirectory() + "/" + file;
return fs.promises.writeFile(tmpDirectory, wrapper.file, "base64").then(()=>{
const options = {
destination: wrapper.path,
};
return bucket.upload(tmpDirectory, options).then(() =>{
fs.unlinkSync(tmpDirectory);
return this.getStorageFileFromPathAsync(wrapper.path).then((response)=>{
return res(response);
});
});
}).catch((err)=>{
fs.unlinkSync(tmpDirectory);
System.prototype.writeLog(err);
return rej({code: 500, error: err});
});
});
}
/**
* Retrieve the url of a file in the storage from the path.
* @param {String} path [Path of the file to get the url]
* @return {Object} [Containing te response]
*/
getStorageFileFromPathAsync(path) {
return new Promise((res, rej)=>{
bucket.file(path).makePublic().then(()=>{
bucket.file(path).getMetadata() .then((response)=>{
System.prototype.writeLog({response: response});
const metadata = response[0];
System.prototype.writeLog({metadata: metadata});
return res({code: 200, url: metadata.mediaLink});
});
}).catch((err)=>{
System.prototype.writeLog(err);
return rej({code: 500, error: err});
});
});
}
}
module.exports = Firebase;
现在让我们谈谈代码,因为有些部分我很难理解,但主要的原因是这样的:
-
我们需要在系统的临时目录下创建一个空文件目录。
-
通过使用 fs 库,我们需要打开一个流并将数据转储到我们创建的临时目录中:
fs.promises.writeFile(tmpDirectory, wrapper.file, "base64").then(()=>{
....})
-
我们现在可以使用我们在步骤 1-2 中创建的路径将文件上传到 firebase 存储,但我们还无法访问下载 url。
-
因为我们在更改新创建的文件可见性并最终通过使用 getStorageFileFromPathAsync() 方法获取下载 url 之前作为管理员进行了身份验证。
希望对你有帮助。