Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UrlFetchApp upload file multipart/form-data in Google Apps Script

I need to upload files to a 3rd party service. The files are created on Google Drive, and I get the blob-data for it.

I want to create a multipart request which now looks like this when I do the UrlFetchApp Post.

This is the payload as string. I have some code that generates the payload. Getting it properly formatted is not the problem, it's the format it is supposed to be.

-----------------0.13accb4c42d338
Content-Disposition: form-data; name="source"; filename="Zzapps.jpg"
Content-Type: application/octet-stream

[[[IMAGE DATA HERE -- OMITTED FOR BREVITY]]]

-----------------0.13accb4c42d338
Content-Disposition: form-data; name="filename"

Zzapps.jpg
-----------------0.13accb4c42d338--

This is the piece of code that does the UrlFetchApp command.

var authHeaders = {
   Authorization: 'OAuth2 '+access_token
}
 var params = {
    accept: "application/json",
    method: 'POST',
    payload: payload,
    contentType: 'multipart/form-data; boundary='+boundaryKey,
    headers: authHeaders,
    ContentLength: payload.length,
    muteHttpExceptions: true
}

var resx = UrlFetchApp.fetch(url, params);

The recieving party gives an error (missing source). I am not sure if my multipart-post is okay in the first place, I do not find any testing URL's to check if I do a proper upload.

How could I send blob-data as a multipart upload the proper way? And now I use blob.getDataAsString() <-- is this correct ?

like image 699
Riël Avatar asked Jun 21 '14 09:06

Riël


1 Answers

If you're building the payload string yourself, you want to do blob.getBytes(), not blob.getDataAsString().

However, there's an easier way. Rather than building the payload string yourself, you can just set a javascript object as the payload, and UrlFetchApp will automatically generate the appropriate payload string, select the correct content-type, boundary, and most of the other options. Just use the "name" attribute of the HTML form's input fields as your object keys. For files, use blobs as the key's values.

function sendReportToSteve() {
  var url = "https://example.com/stevedore.html";
  var form = {
    date : new Date(),
    subject : "Happy birthday!",
    comment : "quakehashprismkeepkick",
    attachment1 : DriveApp.getFileById("sH1proy0lradArgravha9ikE").getBlob(),
    attachment2 : DriveApp.getFileById("traCetRacErI3hplVnkFax").getBlob()
  };
  uploadFile(url,form);
}

function uploadFile(url,form) {
  var options = {
    method : "POST",
    payload : form
  };
  var request = UrlFetchApp.getRequest(url,options);   // (OPTIONAL) generate the request so you
  console.info("Request payload: " + request.payload); // can examine it (useful for debugging)
  var response = UrlFetchApp.fetch(url,options);
  console.info("Response body: " + response.getContentText());
}
like image 172
browly Avatar answered Oct 15 '22 01:10

browly