El següent pas en el upload de fitxers, després de posar un input de tipus file amb l'atribut "multiple" és posar els fitxers en una estructura que permeti el seu enviament al servidor. És aquí on entra el FormData.
El FormData és un interface que s'ha afegit a l'objecte XMLHttpRequest nivell 2 i és una estructura formada per un conjunt de valors organitzats en clau/valor (i en el cas dels fitxers a més a més un nom de fitxer).
El suport del FormData es molt ampli en tots els navegadors actuals, desde el IE10, el FFox, etc...
La funció següent té un bucle per afegir els fitxers i una crida Ajax de jQuery. S'assigna a l'event clic del botó upload. L'únic especial que té aquesta crida Ajax és que s'especifiquen dos parametres que normalment no es posen:
- processData: false, fa que el jQuery no transformi les dades que enviem a string, per defecte és true, cal posar-lo a false ja que enviarem dades binàries.
- contentType: false, per defecte és 'application/x-www-form-urlencoded; charset=UTF-8', aquest encoding no ens va bé ja volem algo del tipus: "multipart/form-data"
function Upload() {
var fd = new FormData();
var fitxer = document.getElementById("fitxer");
$.each(fitxer.files, function (j, file) {
fd.append('fitxer' + j, file);
})
$.ajax({
url: 'images.ashx?action=upload&IdPost=' + evIdPost,
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
if (data.indexOf("ERROR:") != -1) {
$("#ui-dialog-title-dialogErr").html("Error uploading imatge");
$("#errmsg").html(data);
$("#dialogErr").dialog("open");
}
else {
RefreshImatges();
$("#ui-dialog-title-dialogOK").html("Imatge/s pujada/es");
$("#okmsg").html("La/les imatge/s s'ha/n pujat correctament");
$("#dialogOK").dialog("open");
}
}
});
}
En el "success", es a dir quan va bé, el que es fa és verificar el que respon el servidor i mostrar els quadres de diàleg corresponents (són del jQuery UI). També es crida a refrescar imatges, el que fa aquesta funció és consultar al servidor quines imatges hi ha associades al post i mostrar-les. Genera dos botons, un per eliminar la imatge i un altra per afegir un enllaç a la textarea on s'editen els posts. IdImatge i PathImatge són les propietats del JSON que arriba del servidor.
function RefreshImatges() {
var IdImatge = "";
var PathImatge = "";
var strHTML = "";
$.ajax({
type: "GET",
url: "images.ashx?action=data&IdPost=" + evIdPost,
success: function(data, textStatus) {
if (data.indexOf("ERROR:") != -1) {
$("#ui-dialog-title-dialogErr").html("Error recuperant dades de les imatges");
$("#errmsg").html(data);
$("#dialogErr").dialog("open");
}
else {
jQuery.each(data, function (i, Imatge) {
IdImatge = Imatge.IdImatge;
PathImatge = Imatge.PathImatge;
strHTML = strHTML + "<td id='img" + IdImatge + "'>";
strHTML = strHTML + "<img src='" + PathImatge + "' /><br />";
strHTML = strHTML + "<img style='cursor: hand; cursor: pointer' src='/Img/trash.png'";
strHTML = strHTML + " onclick='javascript: DeleteImg(" + IdImatge + ")' /> ";
strHTML = strHTML + "<img style='cursor: hand; cursor: pointer' src='/Img/bloc.png'";
strHTML = strHTML + " onclick='javascript: AfegirImatge(\"" + PathImatge + "\");' /></td>";
});
strHTML = "<tr>" + strHTML + "</tr>";
$("#imatges").html(strHTML);
}
}
});
}
S'ha de tenir en compte que per defecte la mida màxima d'un enviament a un IIS és 4MByte. Per tant si la suma de les mides de les imatges supera aquest valor caldrà configurar el IIS perque accepti valors més grans. Un altra punt que no he posat és el tema de la barra de progres. Tal com ho he muntat només es fa un enviament per tots els fitxers, es a dir s'empaqueten totes les imatges juntes i s'envien, només podria posar una sola barra de progres. Si es volen barres de progres individuals s'han d'enviar els fitxers per separat. De totes maneres per posar una barra de progres a una crida Ajax cal fer servir l'object XMLHttpRequest directament, això jQuery ho fa exposant-lo en la propietat "xhr" del seu object $.ajax. Queda algo així:
$.ajax({
[....]
xhr: function() {
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){
myXhr.upload.addEventListener('progress',showProgress, false);
} else {
console.log("Upload progress is not supported.");
}
return myXhr;
}
});
[...]
function showProgress(evt) {
if (evt.lengthComputable) {
var percentComplete = (evt.loaded / evt.total) * 100;
$('#progressbar').progressbar("option", "value", percentComplete );
}
}
|