Google Apps Scripts: import (upload) media from Google Drive to Google Photos?

核能气质少年 提交于 2020-05-15 21:45:47

问题


I see that we can import (upload) media (photos, videos,...) from Google Drive to Google Photos. My goal is: do this task with code.

I have successfully got a list of photos from Google Drive, and I store their IDs in an Array. I have this code:

  var arrId =
  [
   //Some image id...
  ]; 
  var length = arrId.length;
  var driveApplication = DriveApp;
  for(var i=0;i<length;++i)
  {
    var file = driveApplication.getFileById(arrId[i]);
    //Now I got the file, how can I programmatically import this file to Google Photos
  }

I have searched the docs of Google Script, but I couldn't find any API of Google Photos.

Thanks.


回答1:


  • You want to upload an image file in Google Drive to Google Photo.
  • You want to achieve this using Google Apps Script.

If my understanding is correct, how about this answer?

In this answer, I would like to achieve your goal using a Google Apps Script library of GPhotoApp. This library has the method for uploading a file in Google Drive to Google Photo.

Usage:

1. Linking Cloud Platform Project to Google Apps Script Project:

About this, you can see the detail flow at here.

2. Install library

Install this library.

  • Library's project key is 1lGrUiaweQjQwVV_QwWuJDJVbCuY2T0BfVphw6VmT85s9LJFntav1wzs9.
IMPORTANT

This library uses V8 runtime. So please enable V8 at the script editor.

About scopes

This library use the following 2 scopes. In this case, when the library is installed, these scopes are automatically installed.

  • https://www.googleapis.com/auth/photoslibrary
  • https://www.googleapis.com/auth/script.external_request

Sample script 1:

At first, please retrieve the album ID you want to upload. For this, please use the following script.

function getAlbumList() {
  const excludeNonAppCreatedData = true;
  const res = GPhotoApp.getAlbumList(excludeNonAppCreatedData);
  console.log(res.map(e => ({title: e.title, id: e.id})))
}

Sample script 2:

Using the retrieved album ID, you can upload the image files to Google Photo. In this sample script, arrId of your script is used.

function uploadMediaItems() {
  const albumId = "###";  // Please set the album ID.
  var arrId =
  [
   //Some image id...
  ]; 

  const items = arrId.map(id => {
    const file = DriveApp.getFileById(id);
    return {blob: file.getBlob(), filename: file.getName()};
  });
  const res = GPhotoApp.uploadMediaItems({albumId: albumId, items: items});
  console.log(res)
}

Note:

  • In my environment, I could confirm that the above scripts worked.

References:

  • Photos Library API
  • GPhotoApp



回答2:


Upload File and Insert into Photo Library

You will need to insure that this is a GCP and have the Drive API and Photo Library API enabled.

I'm using the following scopes:

https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/photoslibrary 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

The next thing is that you cannot upload to albums created by a User. You need to create you own albums from a script.

Here's what I used:

function createAlbumByScript() {
  var requestBody={"album":{"title":"Uploads1"}};
  var requestHeader={Authorization: "Bearer " + ScriptApp.getOAuthToken()};
  var options = {
    "muteHttpExceptions": true,
    "method" : "post",
    "headers": requestHeader,
    "contentType": "application/json",
    "payload" : JSON.stringify(requestBody)
  };
  var response=UrlFetchApp.fetch("https://photoslibrary.googleapis.com/v1/albums",options);
  Logger.log(response);
}

I built an upload dialog as follows:

images.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= include('resources') ?>
    <?!= include('css') ?>
  </head>
  <body>
    <?!= include('form') ?>
    <?!= include('script') ?>
  </body>
</html>

resources.html:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

css.html:

<style>
body {background-color:#ffffff;}
input[type="button"],input[type="text"]{margin:0 0 2px 0;}
#msg{display:none;}
</style>

script.html:

<script>    
  $(function(){  
    google.script.run
    .withSuccessHandler(function(vA) {
    $('#sel1').css('background-color','#ffffff');
      updateSelect(vA);
    })
    .getSelectOptions();
  });

  function updateSelect(vA,id){
    var id=id || 'sel1';
    var select = document.getElementById(id);
    select.options.length = 0; 
    for(var i=0;i<vA.length;i++)
    {
      select.options[i] = new Option(vA[i][0],vA[i][1]);
    }
  }    

  function displayAlbum() {
    var albumId=$('#sel1').val();
    var aObj={id:albumId};
    google.script.run
    .withSuccessHandler(function(iObj){
      $('#album').html(iObj.html);
      $('#msg').html(iObj.message);
    })
    .getAlbumDisplay(iObj);
  }

  function uploadFile(form) {
    console.log('form.elements.Destination.value= %s',form.elements.Destination.value);
    console.log('format.elements.FileName.value= %s',form.elements.FileName.value);
    $('#msg').css('display','block');
    $('#msg').html('UpLoading...Please Wait');
    const file=form.File.files[0];
    const fr=new FileReader();//all this FileReader code originally came from Tanaike
    fr.onload=function(e) {
      const obj={FileName:form.elements.FileName.value,Destination:form.elements.Destination.value,mimeType:file.type,bytes:[...new Int8Array(e.target.result)]};//this allowed me to put the rest of the Form.elements back into the object before sending it to google scripts
      google.script.run
      .withSuccessHandler(function(msg){
        $('#msg').css('display','block');
        $('#msg').html(msg);
      })
      .uploadFile(obj);
    }
    fr.readAsArrayBuffer(file);
  }

form.html:

<form>
  <br /><select id="sel1" name="Destination"></select> Upload Destination
  <br /><input type="text" name='FileName' /> File Name
  <br /><input type="file" name='File'; />
  <br /><input type="button" value="Upload" onClick="uploadFile(this.parentNode);" />
  <br /><input type="button" value="Close" onclick="google.script.host.close();" />
  <div id="msg"></div>
</form>

code.gs:

function listFiles() {
  var files = Drive.Files.list({
    fields: 'nextPageToken, items(id, title)',
    maxResults: 10
  }).items;
  for (var i = 0; i < files.length; i++) {
    var file = files[i];
    Logger.log('\n%s-Title: %s Id: %s',i+1,file.title,file.id);
  }
}

function uploadFile(obj) {
  SpreadsheetApp.getActive().toast('Here');
  var folder=DriveApp.getFolderById('1VAh2z-LD6nHPuHzgc7JlpYnPbOP_ch33');
  if(!obj.hasOwnProperty('FileName'))obj['FileName']="NoFileName";
  var blob = Utilities.newBlob(obj.bytes, obj.mimeType, obj.FileName);
  var rObj={};
  var ts=Utilities.formatDate(new Date(), Session.getScriptTimeZone(),"yyMMddHHmmss");
  var file=folder.createFile(blob).setName(obj.FileName + '_' + ts);
  rObj['file']=file;
  rObj['filename']=file.getName();
  rObj['filetype']=file.getMimeType();
  rObj['id']=file.getId();
  if(obj.Destination!=0){
    var uObj={albumid:obj.Destination,fileid:rObj.id,filename:rObj.filename};
    //Logger.log(JSON.stringify(uObj));
    addFileToPhotoLibrary(uObj);
    var msg=Utilities.formatString('<br/>File: %s<br />Type: %s<br />Folder: %s<br />File Added to Photo Library',rObj.filename,rObj.filetype,folder.getName());
    return msg;
  }else{
    var msg=Utilities.formatString('<br/>File: %s<br />Type: %s<br />Folder: %s',rObj.filename,rObj.filetype,folder.getName());
    return msg;
  }
}

function getUploadToken_(imagefileId) {
  var file=DriveApp.getFileById(imagefileId);
  var headers = {
    "Authorization": "Bearer " + ScriptApp.getOAuthToken(),
    "X-Goog-Upload-File-Name": file.getName(),
    "X-Goog-Upload-Protocol": "raw"
  };
  var options = {
    method: "post",
    headers: headers,
    contentType: "application/octet-stream",
    payload: file.getBlob()
  };
  var res = UrlFetchApp.fetch("https://photoslibrary.googleapis.com/v1/uploads", options);
  return res.getContentText()
}


function addFileToPhotoLibrary(uObj) {
  Logger.log(JSON.stringify(uObj));
  var imagefileId=uObj.fileid;  // Please set the file ID of the image file.
  var albumId=uObj.albumid;  // Please set the album ID.
  var uploadToken=getUploadToken_(imagefileId);

  var requestHeader = {Authorization: "Bearer " + ScriptApp.getOAuthToken()};
  var requestBody = {
    "albumId": albumId,
    "newMediaItems": [{
      "description": "Description",
      "simpleMediaItem": {
      "fileName": uObj.filename,
      "uploadToken": uploadToken
    }}]
  };
  var options = {
    "muteHttpExceptions": true,
    "method" : "post",
    "headers": requestHeader,
    "contentType": "application/json",
    "payload" : JSON.stringify(requestBody)
  };
  var response = UrlFetchApp.fetch("https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate", options);
  Logger.log(response);
}

function createAlbumByScript() {
  var requestBody={"album":{"title":"Uploads1"}};
  var requestHeader={Authorization: "Bearer " + ScriptApp.getOAuthToken()};
  var options = {
    "muteHttpExceptions": true,
    "method" : "post",
    "headers": requestHeader,
    "contentType": "application/json",
    "payload" : JSON.stringify(requestBody)
  };
  var response=UrlFetchApp.fetch("https://photoslibrary.googleapis.com/v1/albums",options);
  Logger.log(response);
}

function  launchUploadDialog() {
  loadOptionsPage();
  var ui=HtmlService.createTemplateFromFile('images').evaluate();
  SpreadsheetApp.getUi().showModelessDialog(ui, "Image Upload Dialog")
}

function loadOptionsPage() {
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Options');
  sh.clearContents();
  var dA=[['Destination','Id'],['Uploads Folder',0]];
  var aA=listAlbums();
  aA.forEach(function(a,i){
    dA.push([a.title,a.id]);
  });
  sh.getRange(1,1,dA.length,dA[0].length).setValues(dA);
}

function getSelectOptions() {
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Options');
  var rg=sh.getRange(2,1,sh.getLastRow()-1,2);
  var vA=rg.getValues();
  return vA;
}


来源:https://stackoverflow.com/questions/61345950/google-apps-scripts-import-upload-media-from-google-drive-to-google-photos

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!