Google Apps 脚本:从 Google 驱动器导入(上传)媒体到 Google 照片?

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

我看到我们可以从 Google 驱动器导入(上传)媒体(照片、视频...)到 Google 照片。我的目标是:用代码完成这个任务。

我已成功从 Google 驱动器中获取照片列表,并将它们的 ID 存储在一个数组中。我有这个代码:

  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
  }

我搜索了 the docs of Google Script,但找不到任何 API 的 Google 张照片。

谢谢。

上传文件并插入照片库

您需要确保这是一个 GCP 并启用驱动器 API 和照片库 API。

我正在使用以下范围:

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

接下来是您无法上传到用户创建的相册。您需要通过脚本创建自己的相册。

这是我使用的:

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);
}

我建立了一个上传对话框如下:

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;
}
  • 您想将 Google 驱动器中的图像文件上传到 Google 照片。
  • 您想使用 Google Apps 脚本实现此目的。

如果我的理解是正确的,这个答案怎么样?

在这个回答中,我想使用 GPhotoApp 的 Google Apps 脚本库来实现您的目标。此库具有将 Google 驱动器中的文件上传到 Google 照片的方法。

用法:

1。将云平台项目链接到 Google Apps 脚本项目:

关于这个,你可以在here查看详细流程。

2。安装库

Install this library.

  • 库的项目密钥是 1lGrUiaweQjQwVV_QwWuJDJVbCuY2T0BfVphw6VmT85s9LJFntav1wzs9.
重要的

这个库使用 V8 运行时。所以请在脚本编辑器中启用V8。

关于范围

此库使用以下 2 个范围。在这种情况下,安装库时,会自动安装这些作用域。

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

示例脚本 1:

首先,请检索您要上传的相册ID。为此,请使用以下脚本。

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

示例脚本 2:

使用检索到的相册 ID,您可以将图像文件上传到 Google 照片。在此示例脚本中,使用了您脚本的 arrId

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)
}

注:

  • 在我的环境中,我可以确认上述脚本有效。

参考文献: