This is now possible using Xrm.Device.pickFile. There is currently a bug where it is not working on the Android/IOS/Windows apps, but it does work on a browser.
In the following example I am adding multiple files to the notes section of a form on an entity called new_myentity (with a plural name of new_myentitys).
Create a new button on the form which calls the uploadFiles function (I am not going into the detail of how to add a button to a form here, just google it).
function uploadFiles() {
var pickFileOptions = {};
pickFileOptions.allowMultipleFiles = true;
Xrm.Device.pickFile(pickFileOptions).then(
function (result) {
try {
var recordId = Xrm.Page.data.entity._entityId.guid;
var i;
for (i = 0; i < result.length; i++) {
var note = Object();
note["subject"] = result[i].fileName;
note["filename"] = result[i].fileName;
note["mimetype"] = result[i].mimeType;
note["objectid_new_myentity@odata.bind"] = "/new_myentitys(" + recordId + ")";
note["documentbody"] = result[i].fileContent;
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: Xrm.Page.context.getClientUrl() + "/api/data/v9.0/annotations",
async: false,
data: JSON.stringify(note),
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
XMLHttpRequest.setRequestHeader("OData-MaxVersion", "4.0");
XMLHttpRequest.setRequestHeader("OData-Version", "4.0");
},
success: function (data, textStatus, XmlHttpRequest) {
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
Xrm.Utility.alertDialog("Error: " + textStatus + " " + errorThrown +
XmlHttpRequest.responseText);
}
});
}
alert("" + result.length +" files uploaded");
}
catch (err) {
Xrm.Utility.alertDialog(err);
}
},
function (error) {
Xrm.Utility.alertDialog(error);
});
}