Ajout de l'envoi de photos en HTML5 + WebService REST

De $1

Version de 03:47, 28 Nov 2022

cette version.

Revenir à liste des archives.

Voir la version actuelle

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 :

// 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)

//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); // 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.