This post shows a WinJS/HTML solution to upload multiple images in Windows 8. The same method can apply to other binary files, not limited to images.
Requirement : use HTML POST to upload multiple images to a server at one shot with some form values
Solution : use FormData to build the raw data and use WinJS.xhr to post the data
Code :
/**
* Select multiple images and upload to the server
* @param string url: Server URL
* @param array formFields: other form values to send
* @return a Promise object
*/
function uploadMultipleImages(url, formFields) {
return new WinJS.Promise(function (c, e, p) {
var dataToSend = new FormData();
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.fileTypeFilter.replaceAll([".jpg", ".jpeg"]);
filePicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
filePicker.pickMultipleFilesAsync().then(function (files) {
if (files.length === 0) {
console.log("No file selected");
return;
}
if (formFields && formFields.length > 0) {
formFields.forEach(function (formField) {
for (var key in formField) {
dataToSend.append(key, formField[key]); // Add field value
}
});
}
var imgPromises = []; // Promises for all images access
files.forEach(function (file, index) {
imgPromises.push(file.openAsync(Windows.Storage.FileAccessMode.read));
});
WinJS.Promise.join(imgPromises).then(function (data) { // Wait for all promises
for (var i = 0; i < data.length; i++) {
// data[i] is the file stream
var blob = MSApp.createBlobFromRandomAccessStream("image/jpg", data[i]);
dataToSend.append(files[i].name, blob, files[i].name);
}
var options = { url: url, type: "POST", data: dataToSend };
WinJS.xhr(options).then(function (response) {
c(response);
},
function (xhrError) {
e(xhrError);
});
},
function (joinError) {
e(joinError);
});
});
});
}
Usage example :
var url = "http://testServer/FileUpload/OCR/";
var formValues = [];
formValues.push({ Token: "1234567890" });
uploadMultipleImages(url, formValues).then(function (response) {
var result = response.responseText;
//DO STUFF
});
Note : It's important to include the third parameter when appending blob data:
var blob = MSApp.createBlobFromRandomAccessStream("image/jpg", data[i]);
dataToSend.append(files[i].name, blob, files[i].name);
This will result in following HTTP POST:
-----------------------------multipart-form-data-boundary
Content-Disposition: form-data; name="File1.JPG"; filename="File1.JPG"
Content-Type: image/jpg;
--image binary--
If the third parameter is skipped: formData.append(objName, objValue); then the filename property will be set to "blob" as below which is not accepted in many server implementations:
-----------------------------multipart-form-data-boundary
Content-Disposition: form-data; name="File1.JPG"; filename="blob"
Content-Type: image/jpg;
--image binary--