1

I am getting 404 error on my $.ajax request in Google API. I have these codes,

var asyncLoad = require('react-async-loader');
var CLIENT_ID = '<SOME_ID>';
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"];
  var SCOPES = 'https://www.googleapis.com/auth/drive';

const mapScriptToProps = state => ({
   gapi: {
     globalPath: 'gapi',
     url: 'https://apis.google.com/js/api.js'
   }
});

@asyncLoad(mapScriptToProps)
...

I used async loader of react to get the Google API before the bundle.js. Then I get the gapi in the properties. Here is my next codes for submitting a form.

submitForm(e){
e.preventDefault();
var data = this.refs.file.files[0];
var self = this;
var formData = new FormData();
formData.append('data', data); 
$.ajax({
    url: "https://www.googleapis.com/upload/drive/v3?uploadType=media&access_token="+encodeURIComponent(self.state.token),
    type: "POST",
    processData: false,
    data: formData,
    beforeSend: function (xhr) {
      /* Authorization header */
      xhr.setRequestHeader("Authorization", "Bearer " + self.state.token);
      xhr.setRequestHeader('X-Upload-Content-Length', data.size);
      xhr.setRequestHeader("Content-Type", "image/jpeg");
      xhr.setRequestHeader('X-Upload-Content-Type', "image/jpeg");
  },
    success: function(data){
        if(typeof data === "string") data = JSON.parse(data);
        console.log(data);
        if(data.success){
            console.log("done");
        }else {
            console.log("error");
        }
    }
});

}

So here, I call submitForm function when the button upload is clicked. I have also file input with ref="file". This is run in client (browser) side. I got 404 error.

What I am trying to do here is to upload an image file to google drive. How can I do this right? Any solution for my problem?

JMA
  • 974
  • 3
  • 13
  • 41

2 Answers2

1

The 404 error is caused because the url is missing the files part: https://www.googleapis.com/upload/drive/v3/files?uploadType=media. See Google Drive APIs > REST - Files: create.

I managed to upload an image that was read from <input type="file" accept="image/*"> with FileReader.readAsDataURL() method as follows:

var metadata = {
    name: 'image.jpg',
    mimeType: 'image/jpeg'
}

var user = gapi.auth2.getAuthInstance().currentUser.get();
var oauthToken = user.getAuthResponse(true).access_token;

var boundary = 'foo_bar_baz';
var data = '--' + boundary + '\n';
data += 'content-type: application/json; charset=UTF-8' + '\n\n';
data += JSON.stringify(metadata) + '\n';
data += '--' + boundary + '\n';

var dataURL = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAZAAA/+EKhWh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZ...'
var dataURLparts = dataURL.split(',', 2);
var dataURLheaderParts = dataURLparts[0].split(':');
var dataURLheaderPayloadParts = dataURLheaderParts[1].split(';');

data += 'content-transfer-encoding: ' + dataURLheaderPayloadParts[1] + '\n';
data += 'content-type: ' + dataURLheaderPayloadParts[0] + '\n\n';
data += dataURLparts[1] + '\n';
data += '--' + boundary + '--';

$.ajax({
    type: 'POST',
    url: 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart',
    beforeSend: function (xhr) {
        xhr.setRequestHeader("Authorization", "Bearer " + oauthToken);
     },
     contentType: 'multipart/related; boundary=' + boundary,
     data: data,
     processData: false
 }).done(function(response) {
     console.log(response);
 });
Orienteerix
  • 453
  • 1
  • 9
  • 16
0

After many hours of hair pulling and viewing the same answers. The only thing that worked for me was to change from the multipart request (that Google documents) to using FormData.

Credit to this answer.

While the data arrived to Drive (successful upload), it wasnt processed correctly so image or PDF were not viewable and downloading it showed it was saved in base64.

const metadata = JSON.stringify({
  name: myFile.name,
  mimeType: myFile.type,
});

const requestData = new FormData();

requestData.append("metadata", new Blob([metadata], {
  type: "application/json"
}));

requestData.append("file", items[0].file);

const xhr = new XMLHttpRequest();

xhr.open("POST", "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");

const token = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().access_token;

xhr.setRequestHeader("Authorization", `Bearer ${token}`);

xhr.send(requestData);
poeticGeek
  • 1,001
  • 10
  • 14