问题
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
.
This library uses V8 runtime. So please enable V8 at the script editor.
About scopesThis 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