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

时间:2018-06-03 12:20:19

标签: firebase google-apps-script google-drive-api firebase-storage

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

1 个答案:

答案 0 :(得分:2)

可以使用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-从代码编辑器中选择“资源”和“ Cloud Platform项目”-单击对话框中的内容以转到您的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"
  ]
}

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

allow read, write: if request.auth != null;

Firebase Storage Rules

获取OAuth令牌:

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

ScriptApp.getOAuthToken();

因此,您不需要OAuth库,不需要任何SDK,不需要对客户端代码进行任何操作,不需要Firebase服务帐户或旧版的特殊信息数据库秘密。

代码:

此代码将图像文件从Google云端硬盘上传到Firebase存储

注意!任何超过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
}
}