如何使用 Apps Script 从谷歌驱动器上传文件到 firebase 存储?

use*_*945 4 google-apps-script firebase google-drive-api firebase-storage

我需要一些用户能够将文件上传到 firebase 存储,但他们不精通技术,所以我会让他们先上传到驱动器,然后从存储镜像驱动器。问题是,我不知道如何不用托管服务器;google 应用程序脚本无法轻松访问 firebase 存储(尽管它可以访问两个 firebase 数据库),我需要一个服务器来使用 google drive API,这可以使用 firebase 云函数来完成,但我想知道是否有更简单的替代方法。

Ala*_*lls 5

可以使用 Apps 脚本将图像文件上传到 Firebase 存储。

有4个关键的事情需要做:

  • 启用“Google Cloud Storage JSON API”
  • 获取 Firebase 存储的“存储桶”名称
  • 将“ https://www.googleapis.com/auth/devstorage.read_write ”范围以及已经需要的所有其他范围添加到 appsscript.json 清单文件。
  • 在 Firebase 存储规则中启用“写入”访问权限

您需要获取 OAuth 令牌,但不需要 OAuth 库。

启用“Google Cloud Storage JSON API”

这需要为将上传文件的 Google 帐户完成。此处描述的解决方案用于上传 Apps 脚本项目和 Firebase 存储属于同一 Google 帐户的文件。

  • 转到您的 Google Cloud Platform - 从代码编辑器中选择“Resources”和“Cloud Platform project” - 单击对话框中的某些内容以转到您的 Cloud Platform。找到“API 和服务”部分。单击“启用 API 和服务”搜索“JSON”启用“Google Cloud Storage JSON API”服务。

获取 Firebase 存储的“存储桶”名称

转到您的 Firebase 存储设置。查找“gs://your-bucket-name.appsspot.com”这是您的存储桶名称。不要包含“gs://”存储桶名称需要在末尾包含“appspot.com”部分。

将“ https://www.googleapis.com/auth/devstorage.read_write ”范围添加到 appsscript.json 清单文件

从脚本编辑器中,选择“文件”和“项目属性”,然后单击“范围”选项卡。复制所有现有范围,并将它们粘贴到某处,以便您可以将它们取回。

从脚本编辑器中,选择“查看”和“显示清单文件”。单击 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"
  ]
}
Run Code Online (Sandbox Code Playgroud)

在 Firebase 存储规则中启用“写入”访问权限

allow read, write: if request.auth != null;
Run Code Online (Sandbox Code Playgroud)

Firebase 存储规则

获取 OAuth 令牌:

您可以通过以下方式获取 OAuth 令牌:

ScriptApp.getOAuthToken();
Run Code Online (Sandbox Code Playgroud)

因此,您不需要 OAuth 库,不需要任何 SDK,不需要对客户端代码执行任何操作,不需要来自 firebase 服务帐户或旧数据库机密的特殊信息。

编码:

此代码将图像文件从 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"});
}
Run Code Online (Sandbox Code Playgroud)

代码第一次运行时,如果用户没有启用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
}
}
Run Code Online (Sandbox Code Playgroud)