Les nouvelles APIs « HTML5 » apportent des nouveautés intéressantes comme la File API, permettant de faire du Drag n Drop de fichiers directement depuis sa machine vers une page web. Très pratique pour éviter d’utiliser les « input type file » classiques (boutons « Parcourir… »), surtout quand vous avez plusieurs fichiers à uploader.
Un bon exemple d’utilisation est celui de http://cartodb.com/ (après inscription) sur lequel on peut envoyer un fichier SIG ShapeFile qui n’est pas constitué d’un seul fichier mais de 5/6 fichiers différents. Il est plus pratique de faire glisser les 6 fichiers vers la page web que de créer une archive zip à uploader.
Bref, on va voir comment faire cela de manière simple avec jQuery et Play Framework côté serveur.
Le composant jQuery File Upload
La File API n’est pas facile à manipuler, avec notamment pas mal de cas spéciaux et des comportements qui diffèrent selon les navigateurs. Il y a donc plusieurs librairies qui ont émergé comme uploadify (merci @clacote). Pour ma part, j’ai trouvé ce composant assez puissant qui fonctionne plutôt bien, le jQuery File Upload:
http://blueimp.github.com/jQuery-File-Upload/
Première chose à faire, aller récupérer le code source (et lire les très bonnes docs accessoirement):
https://github.com/blueimp/jQuery-File-Upload/downloads
Application Play Framework 1.x
Si vous n’avez pas téléchargez Play, rendez-vous sur le site officiel. Prenez la 1.2.5:
http://www.playframework.org/download
Dans ce tutorial, on utilisera la 1.x (v1.2.5 lors de l’écriture de cet article). Créez une application si vous n’en avez pas déjà une:
play new tuto-upload
Puis lancez la commande qui permet d’ouvrir le projet dans votre IDE préféré (« play idealize » pour IntelliJ par exemple).
Copiez les fichiers du composant jQuery File Upload que vous avez téléchargé dans le dossier /public/javascripts de votre application. Prenez tout ce qu’il y a dans « /js/ » et copiez-le dans /public/javascripts/ ». Prenez aussi ce fichier qui va se charger de faire du templating pour jQuery (jQ Templates):
http://blueimp.github.com/JavaScript-Templates/tmpl.min.js

Mettez ensuite le contenu de /css/ dans /stylesheets/. Au passage, allez aussi chercher le CSS de Twitter Bootstrap, qui va donner une bonne tête à votre page:
http://twitter.github.com/bootstrap/assets/css/bootstrap.css
Le template de base de Play qui sert de squelette pour vos pages (app/views/main.html) contient déjà jQuery, rien à changer de ce côté là. On va travailler dans le fichier index.html directement.
On va commencer par rajouter les links vers les fichiers JS que l’on vient de copiez en utilisant les hooks « moreScripts » et « moreStyles » + les balises Groovy #{script} et #{style} qui se chargent de setter les attributs obligatoires autres que src:
#{extends 'main.html' /}
#{set title:'Home' /}
#{set 'moreScripts'}
#{get 'moreScripts' /}
#{script 'vendor/jquery.ui.widget.js'/}
#{script 'jquery.iframe-transport.js'/}
#{script 'tmpl.min.js'/}
#{script 'jquery.fileupload.js'/}
#{script 'jquery.fileupload-fp.js'/}
#{script 'jquery.fileupload-ui.js'/}
#{script 'locale.js'/}
#{/set}
#{set 'moreStyles'}
#{get 'moreStyles' /}
#{stylesheet 'jquery.fileupload-ui.css'/}
#{stylesheet 'bootstrap.css'/}
#{/set}
Création de l’action d’upload
On commence par ajouter une route dans le fichier /conf/routes:
# Home page
GET / Application.index
POST /upload Application.upload
On est bien en POST car on souhaite faire de l’upload. On va créer l’action dans notre controller Application.java:
package controllers;
import play.*;
import play.mvc.*;
import java.io.File;
import java.util.*;
import models.*;
public class Application extends Controller {
public static void index() {
render();
}
public static void upload(File[] files) {
}
}
Maintenant, on va créer notre formulaire à partir de cette action dans notre template Groovy (index.html, là où on a mis les moreScript). Pour cela, Play dispose d’un tag #{form} qui permet de faire du reverse routing et de ne pas avoir à taper l’url d’upload (attribut « action ») à la main, pratique:
#{extends 'main.html' /}
#{set title:'Home' /}
#{set 'moreScripts'}
#{get 'moreScripts' /}
#{script 'vendor/jquery.ui.widget.js'/}
#{script 'jquery.iframe-transport.js'/}
#{script 'jquery.fileupload.js'/}
#{script 'jquery.fileupload-fp.js'/}
#{script 'jquery.fileupload-ui.js'/}
#{script 'locale.js'/}
#{/set}
#{set 'moreStyles'}
#{get 'moreStyles' /}
#{stylesheet 'jquery.fileupload-ui.css'/}
#{/set}
#{form @Application.upload() , id:'fileupload', enctype:'multipart/form-data'}
#{/form}
On lui a juste ajouté un simple id pour plus tard et un enctype qui dit que l’on va faire de l’upload.
On va lancer notre application pour voir ce que cela donne. Lancez la commande :
play run
Le serveur Play est lancé sur le port 9000. Rendez-vous donc sur :
http://localhost:9000/
Si tout va bien, vous devriez arriver sur une page blanche. Allez voir la source de la page et vous verrez que votre formulaire est bien là:
<form action="/upload" method="POST" accept-charset="utf-8" enctype="multipart/form-data" id="fileupload" ><input type="hidden" name="authenticityToken" value="58abd56b3f8b6c62a0e0180b59cc65e1e74a6b43">
</form>
Maintenant, on va ajouter le composant jQuery File Upload.
Lire la suite →