4

C# Here if it matters. What I am trying to do is allow users on mobile phones (or desktops) to upload files to my web server. I have the picker built, got the auth all figured out for the scope drive.readonly.

But what I keep seeing in the examples when it comes time to download the file is they download it using Javascript and then upload it again to the server. I would like to get it from my server. I have this working fine with Dropbox, but google is a problem.

I followed the guide here: https://developers.google.com/picker/docs/

But then I send the fileId and token to the server:

 function pickerCallback(data) {
    if (data.action == google.picker.Action.PICKED) {
        var datastring = "url=" + data.docs[0].url + "&name=" + data.docs[0].name + "&mimetype=" + data.docs[0].mimetype + "&fileId=" + data.docs[0].id + "&token=" + oauthToken;
            $.ajax({
                type: "POST",
                url: "/FileUpload/GetGoogleDriveFile/",
                data: datastring,
                dataType: "json",
                success: function (data) {
                    if (data.success != null && data.success == true) {
                        window.location.href = "@Html.Raw(AfterUploadDestination)";
                    }
                    else
                    {
                        alert("Error: " + data.ErrorMsg);
                    }
                },
                error: function (xhr, textStatus, errorThrown) {
                    console.log(xhr.responseText);
                }
            });


        googlepicker.setVisible(false);
    }
}

And then on the server I have something like...

 var client = new System.Net.WebClient();
            client.Headers.Set(HttpRequestHeader.Authorization, "Bearer " + file.token);

then something to consume the file:

doc.Contents = client.DownloadData(string.Format("https://www.googleapis.com/drive/v3/files/{0}?alt=media", file.fileId));

The problem is that the file is not just the binary stream of the file but the webpage itself that google displays when you go to the site with that link.

How in the world do I just download the file?

Thanks in advance and I hope this wasn't so long that no one reads it.

Paul Perrick
  • 496
  • 9
  • 22
  • Perhaps I need to go with a solution similar to this one: https://stackoverflow.com/a/29290636/881954 Re authenticate on the server side. What a drag though if the user gets another popup after they already approved my app and selected a file. – Paul Perrick Jul 25 '17 at 03:58

3 Answers3

1

You may check this documentation on how to open files using the Google Picker API. When a user selects a file from the list, the file ID is returned, and the ID may be used by your app to access the file. After obtaining the file ID from the picker when opening files, an application can then fetch the file metadata and download the file content as described in the reference documentation for files.get.

abielita
  • 13,147
  • 2
  • 17
  • 59
  • 1
    Thanks for the response, but that's what I'm doing and it doesn't work. https://developers.google.com/drive/v2/reference/files/get GET https://www.googleapis.com/drive/v2/files/fileId I've tried v2 and v3 in the path and about 5 different variations that I've seen in documentation: https://www.googleapis.com/drive/v2/files/{0}?key={1} https://www.googleapis.com/drive/v3/files/{0}?alt=media https://drive.google.com/uc?id={0}&export=download https://www.googleapis.com/drive/v2/files/{0}?alt=media Each of those points to a webpage response, and not the file download. – Paul Perrick Jul 25 '17 at 03:49
1

It was me.

I asked Google what the problem could be and support came back with, you need to create a Client ID of Type "Other". So when it didn't work I assumed it was my code.

All I needed to do was use the came Client ID as the Website (Type of Web Application) and create a specific API Key for the picker to use.

For anyone who has issues, this is the meat of the code:

So my Client code is:

function pickerCallback(data) {
        if (data.action == google.picker.Action.PICKED) {
            var datastring = "url=" + data.docs[0].url + "&name=" + data.docs[0].name + "&mimetype=" + data.docs[0].mimetype + "&fileId=" + data.docs[0].id + "&token=" + oauthToken;
                $.ajax({
                    type: "POST",
                    url: "/FileUpload/GetGoogleDriveFile/",
                    data: datastring,
                    dataType: "json",
                    success: function (data) {
                        if (data.success != null && data.success == true) {
                            window.location.href = "@Html.Raw(AfterUploadDestination)";
                        }
                        else
                        {
                            alert("Error: " + data.ErrorMsg);
                        }
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log(xhr.responseText);
                    }
                });
            googlepicker.setVisible(false);
        }
    }

Server Code is:

 public class GoogleFileDetails
        {
            public string url { get; set; }
            public string name { get; set; }
            public int mimetype { get; set; }
            public string fileId { get; set; }
            public string token { get; set; }
        }

[HttpPost]
 public ActionResult GetGoogleDriveFile(GoogleFileDetails file) {

            byte[] contents = null;
            try
            {
                var client = new System.Net.WebClient();
                client.Headers.Set(HttpRequestHeader.Authorization, "Bearer " + file.token);
                contents = client.DownloadData(string.Format("https://www.googleapis.com/drive/v2/files/{0}?alt=media", file.fileId));
            } catch etc...
Paul Perrick
  • 496
  • 9
  • 22
1

I use this code to download a binary image from drive using google picker. The trick part is in xhr.responseType = 'blob';

var xhr = new XMLHttpRequest();
xhr.open('GET', THE_PREVIOUSLY_GOTTEN_DOWNLOAD_URL);
xhr.setRequestHeader('Authorization', 'Bearer ' + THE_OBTAINED_OAUTHTOKEN);
xhr.responseType = 'blob';

xhr.onload = function () {

   // Better trigger and event and manage the response outside the onload function. 
   // Just for demo purposes:

   $('#THE_IMG_ID').attr( 'src', URL.createObjectURL(xhr.response) );
};

xhr.onerror = function () {
};

xhr.send();
Samuel Vicent
  • 991
  • 10
  • 16