Introduction
Dans ce TP vous allez rajouter la possibilité d'insérer des images dans un article que l'on poste dans le blog. Vous vous baserez sur l'exemple "drag'n'drop d'images en HTML5", vous prendre l'exemple qui permet indifféremment d'utiliser des champs <input type=file...> ou <input type=dir...> ou drag'n'drop, proposés sur cette page d'exemples.
Côté serveur, vous devrez écrire un web service capable de récupérer une ou plusieurs images en base 64 sous la forme d'un fichier, et la sauvegarder quelque part. Vous modifierez également le web service qui renvoie les articles pour que chaque article renvoyé contienne aussi les images associées.
Principe de l'envoi d'un formulaire contenant des images en AJAX/jQuery
Le format multipart permet d'envoyer tout un formulaire en une seule requête, même si ce formulaire contient des objets de type "file".
Exemple de requête Ajax POST en jQuery :
-
-
-
- var data = new FormData();
-
- data.append('titre', $("#titre").value);
- data.append('contenu', $("#contenu").value);
-
-
- jQuery.each($('#file')[0].files, function(i, file) {
- data.append('file-'+i, file);
-
- });
-
- $.ajax({
- url: 'resources/article/createAvecImages',
- data: data,
- cache: false,
- contentType: false,
- processData: false,
- type: 'POST',
- success: function(data){
- alert(data);
- }
- });
// On construit un objet qui va contenir les champs du formulaire
// Notamment, certains champs qui correspondront aux images
// selectionnees
var data = new FormData();
// champs du formulaire titre et contenu...
data.append('titre', $("#titre").value);
data.append('contenu', $("#contenu").value);
// et les images
jQuery.each($('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
// soumission par POST au WS
$.ajax({
url: 'resources/article/createAvecImages',
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
Il est impératif d'avoir : contentType : false, sinon jQuery rajoute lui-même un Content-type qui n'est pas bon. Vous devez aussi mettre processData à false sinon jQuery essaiera de transformer le contenu du formulaire en String.
Liens web pour explications : http://stackoverflow.com/questions/5392344/ seconde réponse est la bonne.
Ajax et jQuery : http://www.w3schools.com/jquery/jquery_ref_ajax.asp
Preparer l'image pour qu'elle soit au format binaire
Dans l'exemple suivant le soucis vient du fait que les images sont encodées en base 64. Il existe un moyen de les mettre au format binaire (code tiré de l'article suivant : http://stackoverflow.com/questions/4...rmdata/5100158)
-
- function dataURItoBlob(dataURI, callback) {
-
-
-
- var byteString;
- if (dataURI.split(',')[0].indexOf('base64') >= 0) {
- byteString = atob(dataURI.split(',')[1]);
- } else {
- byteString = unescape(dataURI.split(',')[1]);
- }
-
-
- var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
-
-
- var ab = new ArrayBuffer(byteString.length);
- var ia = new Uint8Array(ab);
- for (var i = 0; i < byteString.length; i++) {
- ia[i] = byteString.charCodeAt(i);
- }
-
-
- var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder;
- var bb = new BlobBuilder();
- bb.append(ab);
- return bb.getBlob(mimeString);
- }
//credit http://stackoverflow.com/a/8782422/52160
function dataURItoBlob(dataURI, callback) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = unescape(dataURI.split(',')[1]);
}
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder;
var bb = new BlobBuilder();
bb.append(ab);
return bb.getBlob(mimeString);
}
//credit http://stackoverflow.com/a/8782422/52160 function dataURItoBlob(dataURI, callback) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs var byteString; if (dataURI.split(',')[0].indexOf('base64') >= 0) { byteString = atob(dataURI.split(',')[1]); } else { byteString = unescape(dataURI.split(',')[1]); } // separate out the mime component var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // write the bytes of the string to an ArrayBuffer var ab = new ArrayBuffer(byteString.length); var ia = new Uint8Array(ab); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } // write the ArrayBuffer to a blob, and you're done var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder; var bb = new BlobBuilder(); bb.append(ab); return bb.getBlob(mimeString); }
Et voilà un exemple d'envoi en AJAX qui utilise cette fonction (tiré de : http://www.raymondcamden.com/index.c...h-getUserMedia). c'est la ligne 9 qui est intéressante.
- function snapshot() {
- $("#result").html("<p><i>Working hard for the money...</i></p>");
-
- canvas.width = video.videoWidth;
- canvas.height = video.videoHeight;
- canvas.getContext('2d').drawImage(video, 0, 0);
-
- var data = canvas.toDataURL('image/jpeg', 1.0);
- newblob = dataURItoBlob(data);
-
- var formdata = new FormData();
- formdata.append("api_key", faceKey);
- formdata.append("api_secret", faceSecret);
- formdata.append("filename","temp.jpg");
-
- formdata.append("file",newblob);
-
- $.ajax({
- url: 'http://api.face.com/faces/detect.json?attributes=age_est,gender,mood,smiling,glasses',
- data: formdata,
- cache: false,
- contentType: false,
- processData: false,
- dataType:"json",
- type: 'POST',
- success: function (data) {
- handleResult(data.photos[0]);
- }
-
- });
- }
function snapshot() {
$("#result").html("<p><i>Working hard for the money...</i></p>");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
var data = canvas.toDataURL('image/jpeg', 1.0);
newblob = dataURItoBlob(data); // HERE Base64 -> binary
var formdata = new FormData();
formdata.append("api_key", faceKey);
formdata.append("api_secret", faceSecret);
formdata.append("filename","temp.jpg");
formdata.append("file",newblob);
$.ajax({
url: 'http://api.face.com/faces/detect.json?attributes=age_est,gender,mood,smiling,glasses',
data: formdata,
cache: false,
contentType: false,
processData: false,
dataType:"json",
type: 'POST',
success: function (data) {
handleResult(data.photos[0]);
}
});
}
Partie WebService REST de reception
Ici c'est un travail à faire. Inspirez-vous de cette solution qui n'utilise pas de librairie externe. On se repose uniquement sur Jersey. Voir cet article : http://www.mkyong.com/webservices/ja...ple-in-jersey/
Note : dans l'article on parle de dépendances, je pense que ce n'est pas nécessaire avec la version actuelle de Jersey.