10

I'm using google picker in my web app to allow user to browse and select files from his google drive. Once he makes the selection, picker returns various data about selected files, including file ID and URL. My goal is to download the selected files to the server. If I pass the URL to my backend script, it won't be able to download a file that is private. I know I could probably use the provided file ID to access the file via Drive API, but I need an access token for that, so I would need to ask the user to grant me permission using oauth flow. I don't want to do that. If user has selected a file using google picker, he is implicitly giving my app the permission to access the file. Why can't I get a public download URL that I can access without a token? That's how Dropbox chooser works, I believe.

Am I missing something here and is there a way to achieve what I'm trying to do without going through oauth authentication. So, basically what I need is this:

  1. User selects a file using picker
  2. Picker provides a public download URL (temporary URL is OK)
  3. I pass that URL to my backend script, which then downloads the file

Alternatively, I could use a solution like this one:

  1. User selects a file using picker
  2. Picker provides file ID and an oauth access token
  3. I pass the file ID and the token to my backend script, which can then access the Google Drive API using the provided access token and download the file.
Kara
  • 6,115
  • 16
  • 50
  • 57
Pavle Predic
  • 5,790
  • 3
  • 17
  • 17

1 Answers1

7

Finally, I found a solution.

If you want to download a file, you need two variables - oAuthToken and fileId

oAuthToken you get from JS client side when user authenticates. If you use the example from google docs (https://developers.google.com/picker/docs/), the function looks like this:

function handleAuthResult(authResult) {
    if (authResult && !authResult.error) {
        oauthToken = authResult.access_token;
        oauthToken; // <-- THIS IS THE Bearer token
        createPicker();
        }
}

fileId you get from when user picks a file. Again, a modified example from google docs:

function pickerCallback(data) {
    if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
        var doc = data[google.picker.Response.DOCUMENTS][0];
        alert('You picked fileId: ' + doc[google.picker.Document.ID]);
    }
}

Probably you will pass these data as a form request, or through ajax. Simple cURL call from backend to download the file:

$oAuthToken = 'ya29.XXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXX-XXXXXXX-XXXXXX-X-XXXXXXXXXXXX-XXXX';
$fileId = '0B4zzcXXXXXXXXXXXXXXXXXXXXXX';

$getUrl = 'https://www.googleapis.com/drive/v2/files/' . $fileId . '?alt=media';
$authHeader = 'Authorization: Bearer ' . $oAuthToken ;


$ch = curl_init($url);

curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

curl_setopt($ch, CURLOPT_HTTPHEADER, [$authHeader]);

$data = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_errno($ch);


$data = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);

file_put_contents("destination-file.jpg", $data);

Docs about file download: https://developers.google.com/drive/web/manage-downloads Actually, everything was given to us, but we couldn't move our brains a little to make out the actual code :)

Mārtiņš Briedis
  • 17,396
  • 5
  • 54
  • 76
  • Can u please sort out my issue to download a file which user select to my server using php and javascript. I'm following the following link but it is not working. It does not download it in proper format. link: http://stackoverflow.com/questions/23423671/files-downloaded-from-google-drive-usin-picker-are-corrupted?rq=1 – user3653474 Sep 16 '15 at 14:30
  • Martin it is saving 1 byte file with no contents in it. When i open it it shows very short file (no contents), what's the problem i can't understand. Please help to sort out my issue. – user3653474 Sep 16 '15 at 19:30
  • @user3653474 Check if curl executes correctly, check if no errors exist (dump the $error varialbe) – Mārtiņš Briedis Sep 17 '15 at 07:30
  • 1
    string(379)" { "error"; { "errors":[{ "domain":"usageLimits","reason":dailyLimitExceededUnreg", message:Daily Limit for Unauthenticated Use Exceeded. Continue use requires signup.". "extendedHelp":"https://code.google.com/apisconsole" }], "code":403, "message":"Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."}}" – user3653474 Sep 17 '15 at 16:08
  • @user3653474 Try downloading the file with PHP, not with javascript. Try to use my example. – Mārtiņš Briedis Sep 18 '15 at 12:14
  • Martin i tried your code and this url http://s7.postimg.org/bx6ygor8b/Untitled_1.png contains the output data, and a file of one byte is saved, every time i run your code, i think it is corrupted file and i checked the permission of oflder it is set to 777, what't the problem i can't understand, please reply. – user3653474 Sep 19 '15 at 05:15
  • @user3653474 Are you sure it's corrupt? With what program are you opening it? What's the extension for the file? – Mārtiņš Briedis Sep 19 '15 at 21:13
  • Martin I'm not sure it is corrupt, 1 byte .jpg blank file is saved every time i run the code. Can u show me the exact code u r running because i have tried many times but it is giving the same result. – user3653474 Sep 21 '15 at 15:17
  • @user3653474 This is my actual code: https://gist.github.com/briedis/797ecd2eaef458573d15 – Mārtiņš Briedis Sep 22 '15 at 06:52