我需要一些非技术人员能够上传文件到 Firebase 存储,因此我将让他们先上传到 Google Drive,并从存储中镜像。问题是,我无法在不托管服务器的情况下解决这个问题;Google Apps 脚本不能轻松访问 Firebase 存储(尽管它可以访问 Firebase 数据库),我需要一个服务器来使用 Google Drive API。这可以使用 Firebase Cloud Functions 来实现,但我想知道是否有更简单的方法。
我需要一些非技术人员能够上传文件到 Firebase 存储,因此我将让他们先上传到 Google Drive,并从存储中镜像。问题是,我无法在不托管服务器的情况下解决这个问题;Google Apps 脚本不能轻松访问 Firebase 存储(尽管它可以访问 Firebase 数据库),我需要一个服务器来使用 Google Drive API。这可以使用 Firebase Cloud Functions 来实现,但我想知道是否有更简单的方法。
使用Apps Script可以将图像文件上传到Firebase存储。
需要完成4个关键步骤:
您需要获取OAuth令牌,但不需要OAuth库。
这需要针对将上传文件的Google帐户完成。本解决方案适用于上传Apps Script项目和Firebase存储由同一Google帐户拥有的文件。
进入您的Firebase存储设置。查找“gs://your-bucket-name.appsspot.com”,这是您的bucket名称。不要包括“gs://”。bucket名称需要在末尾加上“appspot.com”部分。
从脚本编辑器中选择“文件”和“项目属性”,然后单击“范围”选项卡。将所有现有范围复制出来,并将它们粘贴到某个地方,以便您可以重新获取它们。
从脚本编辑器中选择“查看”和“显示清单文件”。单击appsscript.json文件以打开它。将所有现有范围以及“https://www.googleapis.com/auth/devstorage.read_write”范围添加到清单文件中。
{
"timeZone": "America/New_York",
"dependencies": {
},
"webapp": {
"access": "ANYONE_ANONYMOUS",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": [
"https://mail.google.com/",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/script.scriptapp",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/devstorage.read_write"
]
}
allow read, write: if request.auth != null;
您可以使用以下方法获取OAuth令牌:
ScriptApp.getOAuthToken();
所以,您不需要OAuth库,也不需要任何SDK,也不需要在客户端代码中进行任何操作,也不需要从Firebase服务帐户或Legacy Database Secret获取特殊信息。
此代码将来自Google Drive的图像文件上传到Firebase Storage
注意! 任何超过5MB的文件可能需要做一些不同的事情。
function uploadToFirebaseStorage(po) {
try{
var blob,bucketName,bytes,fileID,fileName,folderName,
oA_Tkn,options,pathAndName,response,result,url;
/* See
https://cloud.google.com/storage/docs/uploading-objects?authuser=0
for REST API information
*/
/*
Firebase uses the Google Cloud Storage API
*/
bucketName = "your-bucket-name.appspot.com";
folderName = "folder_name";
fileName = "file_name";
pathAndName = folderName + "/" + fileName;
fileID = po.fileId;
//curl "https://www.googleapis.com/upload/storage/v1/b/[BUCKET_NAME]/o?uploadType=media&name=[OBJECT_NAME]"
url = 'https://www.googleapis.com/upload/storage/v1/b/' + bucketName + '/o?uploadType=media&name=' + pathAndName;
blob = DriveApp.getFileById(fileID).getBlob();
//Logger.log('blob.getContentType(): ' + blob.getContentType())
bytes = blob.getBytes();
//Logger.log('bytes: ' + bytes)
oA_Tkn = ScriptApp.getOAuthToken();
options = {
method: "POST",//curl -X POST
muteHttpExceptions: true,
contentLength: bytes.length,
contentType: blob.getContentType(),//curlv-H "Content-Type: [OBJECT_CONTENT_TYPE]"
payload: bytes,
headers: {//curl -H "Authorization: Bearer [OAUTH2_TOKEN]"
Authorization: 'Bearer ' + oA_Tkn
}
}
response = UrlFetchApp.fetch(url, options);
result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
/*
A successful return object looks like:
{
"kind": "storage#object",
"id": "bucket-name.appspot.com/online_store/file_name/abc123",
"selfLink": "https://www.googleapis.com/storage/v1/b/bucket-name.appspot.com/o/online_store%2FAAA_Test",
"name": "folder_Name/file_name",
"bucket": "bucket-name.appspot.com",
"generation": "abc123",
"metageneration": "1",
"contentType": "image/jpeg",
"timeCreated": "2018-10-24T00:47:33.435Z",
"updated": "2018-10-24T00:47:33.435Z",
"storageClass": "STANDARD",
"timeStorageClassUpdated": "2018-10-24T00:47:33.435Z",
"size": "950012",
"md5Hash": "abc123==",
"mediaLink": "https://www.googleapis.com/download/storage/v1/b/bucket-name.appspot.com/o/some_name%2FAAA_Test?generation=abc123&alt=media",
"crc32c": "kIY6Qg==",
"etag": "nwrfwfn="
}
*/
}catch(e) {
Logger.log(e.message + "\n\n" + e.stack)
}
}
function testFB_Upload() {
uploadToFirebaseStorage({fileId:"Put image file ID here"});
}
当代码第一次运行时,如果用户未启用API,则响应中的扩展错误消息提供了一个链接。因此,您可以修改代码以从错误响应中获取Cloud Console链接。该链接直接进入正确的Cloud Console API,因此用户不需要知道如何导航其Cloud Console以查找正确的API。
<head>
<title>Your Site Name</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Firebase App is always required and must be first -->
<script src="https://www.gstatic.com/firebasejs/5.5.7/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.5.7/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.5.7/firebase-storage.js"></script>
<script>
// Initialize Firebase
//Open the project - click Project Overview - Click the </> icon
var config = {
apiKey: "abc123",//Web API key in project settings
authDomain: "your_name.firebaseapp.com",
//databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
projectId: "myID",//In Project Settings
storageBucket: "myDomain.appspot.com"
};
firebase.initializeApp(config);
</script>
</head>
window.srchForFile = function(po) {//client side code in a script tag
//This function is called from a success handler AFTER the file has
//originally been uploaded
try{
/*
po - parameters object - {fileID:'123ABC',folderName:'name_here'}
po.fileID - the ID of the original file that was uploaded
po.folderName - the name of the firebase folder to search
*/
/*
This code assumes that the firebase SDK has been loaded and that the
firebase class is available
*/
var fileID,fileName,imagesRef,spaceRef;
fileID = po.fileId;
fileName = "IMG_" + fileID;//The file name to search for which must
//be exactly the same as the file just uploaded - make sure to use
//a naming convention that is consistent
if (!STORAGE_REF) {
STORAGE_REF = firebase.storage().ref();//firebase SDK must be loaded
}
imagesRef = STORAGE_REF.child(po.folderName);
//console.log('imagesRef: ' + imagesRef);
spaceRef = imagesRef.child(fileName);// Points to the file name
//console.log('spaceRef: ' + spaceRef);
spaceRef.getDownloadURL().then(function(url) {
//console.log('File available at: ' + url);
if (!url) {
url = false;
}
nextStepAfterFileSrch(url);//Now run another function
}).catch(function(error) {//There was an error
// Handle any errors here
nextStepAfterFileSrch(false);
}
);
//DO NOT HAVE ANY CODE HERE OR IT WILL RUN BEFORE THE ABOVE CODE IS
//DONE
} catch(e) {
showErrMsg(e.message);//client side error handling
}
}