Avow Studio
Avow Studio

Reputation: 87

Upload image from URL to Google Drive through Google Drive API Javascript

I am new in Javascript and sorry if my question seems lame to you. I want to upload an image from my website to my Google Drive. I have successfully implemented the Authentication and Folder creation part, but I am confused about the uploading process.
Say this is my code for creating a folder inside Google Drive:

function createFolder(folderName) {
  var parentId = 'xxxxxxx';//some parentId of a folder under which to create the new folder
  var fileMetadata = {
    'name' : folderName,
    'mimeType' : 'application/vnd.google-apps.folder',
    'parents': [parentId]
  };
  gapi.client.drive.files.create({
    resource: fileMetadata,
  }).then(function(response) {
    switch(response.status){
      case 200:
      var file = response.result;
      console.log('Created Folder Id: ', file.id);
      uploadImage(file.id);
      break;
      default:
      console.log('Error creating the folder, '+response);
      break;
    }
  });
}

Now I want to upload my image from this url: https://xxxxxx.com into the newly created folder from upper response (file.id)

This is what I got in Google API documentation, but where should I put/attached my url in it?

function uploadImage(folderId) {
  var fileMetadata = {
    'name': 'photo.jpg',
    parents: [folderId]
  };
  var media = {
    mimeType: 'image/jpeg',
    body: fs.createReadStream('files/photo.jpg')
  };
  drive.files.create({
    resource: fileMetadata,
    media: media,
    fields: 'id'
  }, function (err, file) {
    if (err) {
      // Handle error
      console.error(err);
    } else {
      console.log('File Id: ', file.id);
    }
  });
}   

Thanks a lot in advance.

Upvotes: 1

Views: 3487

Answers (2)

Tanaike
Tanaike

Reputation: 201583

I believe your goal as follows.

  • You want to download a file from an URL and upload the downloaded file to Google Drive using Javascript.
  • In your case, your gapi.client can be used for uploading the file to Google Drive.

Modification points:

  • In the current stage, unfortunately, it seems that gapi.client.drive.files.create cannot still send the request including the content. Ref So in this case, I would like to propose to use fetch as a workaround. When fetch is used, the file content and metadata can be requested with multipart/form-data.
  • In this workaround, the access token is used from gapi.client. So this script supposes that your gapi.client can be used for uploading the file. Please be careful this.

Modified script:

const url = "###";  // Please set the URL.
const fileName = "sample filename";
const folderId = "###";  // Please set the folder ID.

fetch(url).then(res => res.blob()).then(blob => {
  const form = new FormData();
  form.append('metadata', new Blob([JSON.stringify({name: fileName, parents: [folderId]})], {type: 'application/json'}));
  form.append('file', blob);
  fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', {
    method: 'POST',
    headers: new Headers({'Authorization': 'Bearer ' + gapi.auth.getToken().access_token}),
    body: form
  }).then(res => res.json()).then(val => console.log(val));
});
  • When you run this script, the following result can be seen at the console. (When the URL is the direct link of Jpeg image file.)

      {
        "kind": "drive#file",
        "id": "###",
        "name": "sample filename",
        "mimeType": "image/jpeg"
      }
    

Note:

  • In this case, uploadType=multipart is used. So the maximum file size is 5 MB. Please be careful this. When you want to use more than 5 MB, please check Resumable upload. Ref

References:

Added:

In order to avoid the error related to CORS, as an another method, I would like to propose to use the Web Apps as a wrapper. In this case, the client side is Javascript. This Javascript can be used at outside of the Google.

Usage:

Please do the following flow.

1. Create new project of Google Apps Script.

Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.

If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.

2. Prepare script.

Please copy and paste the following script (Google Apps Script) to the script editor. This script is for the Web Apps.

Server side: Google Apps Script

This script is used for Web Apps. In this case, the Web Apps is used as the wrapper.

function doGet(e) {
  const imageUrl = e.parameter.imageUrl;
  const res = UrlFetchApp.fetch(imageUrl);
  if (res.getResponseCode() != 200) throw new Error("Image couldn't be retrieved.");
  const blob = res.getBlob();
  const file = DriveApp.getFolderById(e.parameter.folderId).createFile(blob.setName(e.parameter.filename));
  const obj = {id: file.getId(), name: file.getName(), mimeType: file.getMimeType()};
  return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON);
}

3. Deploy Web Apps.

  1. On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
  2. Select "Me" for "Execute the app as:".
    • By this, the script is run as the owner.
  3. Select "Anyone, even anonymous" for "Who has access to the app:".
  4. Click "Deploy" button as new "Project version".
  5. Automatically open a dialog box of "Authorization required".
    1. Click "Review Permissions".
    2. Select own account.
    3. Click "Advanced" at "This app isn't verified".
    4. Click "Go to ### project name ###(unsafe)"
    5. Click "Allow" button.
  6. Click "OK".
  7. Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
    • When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.

4. Upload a file from client side to server side.

Client side: HTML & Javascript

Please set the URL of your Web Apps to the following script. And, please set the filename and folder ID.

const imageUrl = "###"; // Please set the URL of image.

const url = "https://script.google.com/macros/s/###/exec"; // Please set the URL of Web Apps.
const qs = new URLSearchParams({
  imageUrl: imageUrl,
  filename: "sample filename",
  folderId: "###", // Please set folder ID.
});
fetch(`${url}?${qs}`).then((res) => res.json()).then(console.log).catch(console.log);
Result:

When above script is run, the following value is returned. You can see the returned value at the console.

{
  "id": "###",
  "name": "###",
  "mimeType": "###"
}

Note:

  • When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to Web Apps. Please be careful this.

References:

Upvotes: 1

Jeff Rush
Jeff Rush

Reputation: 912

Try to upload your photo file using this snippet:

// download file from website 
const http  = require('https')
const fs    = require('fs')

let file    = fs.createWriteStream('Photo001.jpg')
let request = http.get(
    'https://ssl.gstatic.com/ui/v1/icons/mail/rfr/logo_gmail_lockup_default_2x.png', 
    (response) => {
        response.pipe(file)
    })

// upload file to Google Drive
let fileMetadata = {
  'name'    : 'Photo001',
  'mimeType': 'image/jpeg'
}

let media = {
  mimeType  : 'image/jpeg',
  body      : fs.createReadStream('Photo001.jpeg')
}

function uploadFile(auth){

  const drive = google.drive({version: 'v3', auth})

  drive.files.create({
    resource: fileMetadata,
    media   : media,
    fields  : 'id'
  }, (err, res) => {
    if (err) return console.log('The API returned an error: ' + err)
  })

}

Documentation

Upvotes: 1

Related Questions