4
votes

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 ?

1
In a situation like this, I start with the simplest hard coded code that I can get to work, then go from there. Try to get something simple to work first. Have you looked at the Execution Transcript for clues? Do you use Logger.log() to check values? Is your params object getting parsed as an object? If you use Logger.log('params: ' + params); you should see [object:Object] as the value for params. - Alan Wells
Yes. I am trying to send a hardcoded code that works. I cannot see to make one that does the trick. I expect the multipart code to be a string in the params.payload parameter ? - Riël
I know it might be a bit too late, but in this article — ctrlq.org/code/20096-upload-files-multipart-post — the guy nailed it. - a-change
Is this information useful for your situation? github.com/tanaikech/FetchApp - Tanaike

1 Answers

4
votes

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