1
votes

I'm having problems posting images to https://www.googleapis.com/upload/drive/v3/files?uploadType=media. The file is created on my Google Drive, however the jpeg is always 35KB is size, so appears none of the image content ever gets uploaded.

Originally I thought it was bug in vue-google-api however now suspect it's something with the Google Drive API V3. When I try posting an image directly to the API, I experience the same problem.

Request

POST https://www.googleapis.com/upload/drive/v3/files?uploadType=media
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: image/jpeg
Content-Length: 26837
Accept-Language: en-ca
Authorization: Bearer ya29.Gl1pB5BN9khs33ygA9pnIbyxJYp87teqDUfm55EsEHmmPJz0...

/9j/4AAQSkZJRgABAQEASABIAAD//gAMQXBwbGVNYXJrCv/bAIQABwUFBgUFBwYGBggHBwgKEQs...

Response

HTTP/1.1 200 OK

Server: UploadServer
Content-Type: application/json; charset=UTF-8
X-GUploader-UploadID: AEnB2UrjBAKhEMI-rCdzXpfAF3rM3oBABNUVH9AnhFtoXsoRroYV3By4rVqEuU1mn_5rJ2u_msN99Z1m2r-6Lh53fAowxmQ7QGAgWr2bP6cEwfnfV9JE-Vc
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Vary: Origin, X-Origin
Date: Mon, 19 Aug 2019 17:04:18 GMT
Alt-Svc: quic=":443"; ma=2592000; v="46,43,39"
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 118
{
    "kind": "drive#file",
    "id": "16dC3Fv2vKIur426INggTZ6GzDvyRUPrV",
    "name": "Untitled",
    "mimeType": "image/jpeg"
}

Has anyone been able to successfully upload images to Google Drive API V3? Any idea what could be going wrong?

2
"Content-Length: 26837" is this the correct size of jpeg? Try base64 encoding it.pinoyyid
I'm using capacitor.ionicframework.com/docs/apis/camera and getting back the image as a base64 string, then calculating the Content-Length using parseInt(base64.replace(/=/g,"").length * 0.75). Does this look correct?Dale Zak
If you are saying that the string you are uploading is already base64 encoded, then content-length should simply be the length, and you should add a content-transfer-encoding header.pinoyyid

2 Answers

1
votes

How about this modification? About uploadType=media, the metadata cannot be included and I couldn't find the method that the base64 data is uploaded and converted. When I saw the link in your question, I noticed that you have tried 2 methods. One is uploadType=media. Another is uploadType=multipart. At the link, I also confirmed that both scripts don't work.

uploadType=multipart can upload the base64 data and convert it to the binary data. So here, I would like to propose the modification for uploadType=multipart.

Modification points:

I think that your request body is almost correct. But it is required to be modified a little.

  • In your question, you said that the data is converted to base64. In this case, Content-Transfer-Encoding is required to be set to the request body.
  • When the file is uploaded to Google Drive, even if Content-Length is not set, the file can be uploaded.

Modified script:

Please modify contentDisposition() as follows.

body += "--" + boundary
     + "\r\nContent-Disposition: form-data; name=" + key
     + "\r\nContent-type: " + formData[key].type
     + "\r\n\r\n" + formData[key].value + "\r\n";
body += "--" + boundary
     + "\r\nContent-Disposition: form-data; name=" + key
     + "\r\nContent-type: " + formData[key].type
     + (key == "file" ? "\r\nContent-Transfer-Encoding: base64" : "")  // Added
     + "\r\n\r\n" + formData[key].value + "\r\n";

And, please modify uploadGoogleMultipart() as follows.

headers: {
    "Content-Type": "multipart/related; boundary=" + boundary,
    'Content-Length': body.length
},
headers: {
    "Content-Type": "multipart/related; boundary=" + boundary,
},

Note:

  • In this modification, it supposes that you have already been able to upload the file to Google Drive using Drive API.

Reference:

If I misunderstood your question and this was not the direction you want, I apologize.

0
votes

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.

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);