Chlebik
Chlebik

Reputation: 676

Sending multipart form using Dojo xhr with both json and file upload

I've tried to get this working but did not find any soluion. The closest to my problem is this one - Composing multipart/form-data with a different Content-Type on each parts with Javascript (or Angular) - but the question author stopped in between. I cannot.

So this is the story - I got webservice written in .NET. It is POST based - I have to send both - JSON data (with title, content, etc) and also file(s) - just uploaded from user's disc. I am sending this from DOJO Dialog box. What I am actually doing is create AJAX post request and send it to the server.

So I should use 'multipart/form-data'. The problem is that I have to gather data to be send from various sources (not only data provided in form elements). My code looks something like this.

var values = { // here I create simple JS object with data from multiple places };
var formData = new FormData();

formData.append('data', json.stringify(values));   // Object to JSON
var files = document.getElementById("files").files;
var file = files[0];
formData.append("file0", file);

xhr.post('link_to_my_service',  
{ 
    handleAs: "json",
    sync: false,
    data: formData,
    headers: {                     
         'X-Requested-With': '',
         'Content-Type': false,   
         'Accept': 'application/javascript, application/json'
    }
}) // handlers are not important

It goes to the service, the service accepts it ('X-Requested-With' for security passing). My request in console looks like this.

------WebKitFormBoundaryDyeoTyKXhr5oZ1a9
Content-Disposition: form-data; name="data"    
{"key1":"value2","key2":"value1","key3":666,"key4":999}

------WebKitFormBoundaryDyeoTyKXhr5oZ1a9
Content-Disposition: form-data; name="file0"; filename="name_of_my_file.opml"
Content-Type: application/octet-stream

------WebKitFormBoundaryDyeoTyKXhr5oZ1a9--

And it DOES NOT WORK. It happens because of 'data' part of request not having 'Content-Type' set! And I am not able to do that in any way. Suggested solution was to create BLOB and then pass it the JSON string. But it does not work either - it adds 'Content-Type' (skips charset though), but adds filename and also in the console I see that actual contents of this part is empty (although the same is for file - I do not know if Chrome should show me there full cotents of my file).

So now I am stuck - I do not know how to proceed. There is no way I can change the service. Does anybody got any idea how to trick Dojo to achieve my goal? And yes, I am using Dojo 1.10.

Upvotes: 2

Views: 2254

Answers (1)

Sebastian Frey
Sebastian Frey

Reputation: 488

Maybe a little bit late, but better late than never.

The link you marked as closest to your problem, delivers already a solution. (Last answer from Yeo)

So based on that answer, I would try to build up my FormData object like this:

let formData = new FormData();

// add the file to your form data.
formData.append('file', file);    

// create an object like structure in your form data.
for (let key in values) {
  if(values.hasOwnProperty(key)) {
    formData.append(`data[${key}]`, values[key]);
  }
}

// set up your post requests options.
...

let handle = xhr.post(url, options);

And then on the server side, you can parse this back to an object, by iterating over the requests body parts and collecting the fields you need.

Upvotes: 2

Related Questions