Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Google Drive API to download files with Javascript

I want to download files from google drive with javascript API. I have managed to authenticate and load list of files using gapi.client.drive.files request. However, I stuck at downloading those files.
My attempt to download the file:

var request = gapi.client.drive.files.get({
        fileId:id,
        alt:'media'
});
request.execute(function(resp){
        console.log(resp);
});

I have these errors when trying to run the above:

(403) The user has not granted the app 336423653212 read access to the file 0B0UFTVo1BFVmeURrWnpDSloxQlE.

(400) Bad Request

I recognize that the files which aren't google drive file (google doc, google slide) return the 403 error.
I am new to this. Any help and answer is really appreciated.

Update 0

From Google Drive documentation about Handling API Error, here is part of the explanation for 400 errors

This can mean that a required field or parameter has not been provided, the value supplied is invalid, or the combination of provided fields is invalid.

This is because I have alt:'media' in my parameter object.

I tried gapi.client.drive.files.export, but it doesn't work either and it returns (403) Insufficient Permission although my Google Drive account has the edit permission for those files. Here is my code:

var request = gapi.client.drive.files.get({
    fileId:element.id,
});
request.then(function(resp){
    console.log(resp.result);
    type = resp.result.mimeType;
    id = resp.result.id;
    var request = gapi.client.drive.files.export({
        fileId:id,
        mimeType:type
    })
    request.execute(function(resp){
        console.log(resp);
    });
});

Update 1

Based on abielita's answer, I have tried to make an authorized HTTP request but it doesn't download the file. It actually returns the file information in response and responseText attribute in the XMLHttpRequest object.

  function test() {
    var accessToken = gapi.auth.getToken().access_token;
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "https://www.googleapis.com/drive/v3/files/"+'1A1RguZpYFLyO9qEs-EnnrpikIpzAbDcZs3Gcsc7Z4nE', true);
    xhr.setRequestHeader('Authorization','Bearer '+accessToken);
    xhr.onload = function(){
        console.log(xhr);
    }
    xhr.send('alt=media');
  }

______________________________________________________

I found out that I can actually retrieve URLs of all those files from the folder using files' webViewLink or webViewContent attributes.

  • A file which is from Google Drive type (Google Doc, Google Sheet, etc...) will have webViewLink attribute. A webViewLink will open the file in Google Drive.

  • A non Google Drive type file will have webContentLink. A webContentLink will download the file.

My code:

var request = gapi.client.drive.files.list({
    q:"'0Bz9_vPIAWUcSWWo0UHptQ005cnM' in parents", //folder ID
    'fields': "files(id, name, webContentLink, webViewLink)"
  });
request.execute(function(resp) {
        console.log(resp);
}
like image 830
phuwin Avatar asked Jun 16 '16 13:06

phuwin


People also ask

How do I download from Google Drive API?

To download a file stored on Google Drive, use the files. get method with the ID of the file to download and the alt=media URL parameter. The alt=media URL parameter tells the server that a download of content is being requested.

How do I automatically download files from Google Drive?

Settings. Click Show advanced settings and go to Downloads. Click Change and in the pop-up, navigate to the Downloads folder you dragged to your Google Drive folder and click Select. This selection is now your default download location.

How do I download a file using API?

In this article, I will use a demo Web API application in ASP.NET Core to show you how to transmit files through an API endpoint. In the final HTML page, end users can left-click a hyperlink to download the file or right-click the link to choose “ Save Link As ” in the context menu and save the file.

Does Google Drive use JavaScript?

The Drive API is used to interact with Google Drive storage, and supports several popular programming languages, such as Java, JavaScript, and Python.


2 Answers

Based from this documentation, if you're using alt=media, you need to make an authorized HTTP GET request to the file's resource URL and include the query parameter alt=media.

GET https://www.googleapis.com/drive/v3/files/0B9jNhSvVjoIVM3dKcGRKRmVIOVU?alt=media
Authorization: Bearer ya29.AHESVbXTUv5mHMo3RYfmS1YJonjzzdTOFZwvyOAUVhrs

Check here the examples of performing a file download with our Drive API client libraries.

String fileId = "0BwwA4oUTeiV1UVNwOHItT0xfa2M";
OutputStream outputStream = new ByteArrayOutputStream();
driveService.files().get(fileId)
        .executeMediaAndDownloadTo(outputStream);

For the error (403) Insufficient Permission, maybe this is a problem with your access token, not with your project configuration.

The insufficient permissions error is returned when you have not requested the scopes you need when you retrieved your access token. You can check which scopes you have requested by passing your access_token to this endpoint: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ACCESS_TOKEN

Check these links:

  • google plus api: "insufficientPermissions" error

  • Google drive Upload returns - (403) Insufficient Permission

    Remember you are uploading to the service accounts google drive account. If you want to be able to see it from your own Google drive account you are going to have to do an insert of the permissions. to give yourself access

like image 121
abielita Avatar answered Sep 22 '22 15:09

abielita


Task: download the file and create File object; Environment: browser;

const URL = 'https://www.googleapis.com/drive/v3/files';
const FIELDS = 'name, mimeType, modifiedTime';

const getFile = async (fileId) => {
  const { gapi: { auth, client: { drive: { files } } } } = window;
  const { access_token: accessToken } = auth.getToken();
  const fetchOptions = { headers: { Authorization: `Bearer ${accessToken}` } };
  
  const {
    result: { name, mimeType, modifiedTime }
  } = await files.get({ fileId, fields: FIELDS });
  
  const blob = await fetch(`${URL}/${fileId}?alt=media`, fetchOptions).then(res => res.blob());
  const fileOptions = {
    type: mimeType,
    lastModified: new Date(modifiedTime).getTime(),
  };
  
  return new File([blob], name, fileOptions);
};
like image 33
Kirill Skomarovskiy Avatar answered Sep 18 '22 15:09

Kirill Skomarovskiy