Upload de fichiers avec Catalyst

user_icon admin | icon2 Catalyst | icon4 28/8/2007 17h16| Type doc: article| Type File: txt| icon3 No Comment

Upload de fichiers avec Catalyst


1. Le but du jeu

Le but de l'exercice sera de créer un serveur de fichiers en mode Web. Seule la fonction Upload sera implémentée.

Un simple formulaire pourrait faire l'affaire, sauf que là, j'aimerai bien avoir en plus une barre de progression comme l'on peut voir sur certains sites.

En fouillant dans le dépôt SVN de Catalyst j'y ai trouvé mon bonheur : le plugin UploadProgress

2. UploadProgress

Le plugin UploadProgress nous aide dans notre tâche en nous fournissant toute la mécanique Ajax nécessaire à la progression de la barre de chargement en temps réèl.

Pour mettre en pratique ce plugin il est nécessaire de créer un formulaire de saisie du fichier avec une action onsubmit qui lancera l'éxécution de la barre de progression. Il n'est pas nécessaire d'avoir de connaissances Ajax poue utiliser ce plugin.

3. Le squelette de l'application

Avec Catalyst nous créons notre application simplement:

catalyst.pl MonApp

Le rendu des pages sera tripatouillé par Template::Toolkit dont le vue doit être créée.

cd MonApp
perl script/monapp_create.pl view TT TT

Le controleur Upload se chargera du transfert (ce qui correspond à l'url http://le site/upload). On s'empresse de le créer.

perl script/monapp_create.pl controller Upload

Ajoutons tout de suite le formulaire root/form.tt.Il s'agit d'une page qui sera interprétée par Template::Toolkit


    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>Demo Barre de progression avec Catalyst</title>

        <!-- The lazy way... -->
        [% c.upload_progress_javascript %]
</head>

<body>

<div id="form">
    <form action="/upload/save"

          method="post"
          enctype="multipart/form-data"
          onsubmit="return startEmbeddedProgressBar(this)">

        <fieldset>
            <legend>Select a file to upload...</legend>

            <label for="upload_file">File:</label>

            <input type="file" name="file" /><br />

            <br />
            <input type="submit" />
        </fieldset>
    </form>
</div>

<div id="progress"></div>

</body>
</html>

Si on démarre maintenant l'appliction et que l'on s'y connecte on peut visualiser la page d'infos de Catalyst :(

4. La finition

Il reste encore quelques détails à mettre en place:

  • Indiquer à Catalyst de prendre en compte le plugin UploadProgress

  • Préciser la vue par defaut ( de type TT)

  • Configurer le template à utiliser (form.tt)

  • Assurer les redirections

La prise en compte du plugin se fait dans le fichier lib/MonApp.pm (le fichier de configuration de notre application) de plus pour que celui-ci fonctionne il faut ajouté un plugin de gestion de Cache, Cache::FastMmap en l'occurence.


use Catalyst qw/-Debug ConfigLoader Static::Simple UploadProgress Cache::FastMmap/;

Dans ce même fichier j'ajoute la méthode 'default' utiliser par défaut si l'on se connecte à la racine du site. Elle sera chargé de rediriger la requète vers '/upload' le formulaire de saisie.

sub default : Private {
    my ( $self, $c ) = @_;

   $c->res->redirect( $c->uri_for('/upload') );
}

J'ajoute aussi la méthode ' end' pour utiliser par défaut la vue TT précédement créée. Ainsi quelle que soit la requête elle se terminera par cette méthode excepté si le status est de la forme 3xx soit une redirection :)


sub end : Private {
    my ( $self, $c ) = @_;

    return 1 if $c->res->status =~ /^3\d\d$/;
    $c->forward( $c->view('TT') ) unless $c->response->body;
}

La vue pour s'afficher interprète un template TT, c'est le controleur qui lui fourni. Ainsi pour notre controleur Upload nous aurons le template form.tt chargé d'afficher le formulaire de saisie.

Losque que le controleur est accédé par l'url /upload c'est la méthode index qui est appelée. Dans le fichier lib/MonApp/Controller/Upload.pm je modifie la méthode 'index comme ci-dessous.


sub index : Private {
    my ( $self, $c ) = @_;

    $c->stash->{template} = 'form.tt';
}

Il ne reste plus qu'à terminer avec une méthode ' save' dans ce même controleur qui assurera la sauvegarde du fichier.


sub save : Local {
        my ( $self, $c ) = @_;

        my $upload = $c->request->uploads->{file};
        $upload->copy_to( '/tmp/' . $upload->filename );
        $c->forward( 'index' );
}

Encore une dernière chose dont nous aurons besoin sont les fichiers css et js. Le javascript étant utilisé pour l'affichage de la barre de progression en Ajax. Récupérer les répertoires 'css' et 'js' de l'exemple fourni avec le package Catalyst-Plugin-UploadProgress ou plus simplement les sources de cette application.

Je récapitule ...

J'accède à l'url http://mon site/upload, c'est donc le controleur Upload qui est appelé. La méthode par défaut ' index' est alors exécutée. Elle fournie le template a utilisée en l'enregistrant dans le stash (variable utilisée par TT). Le controleur Upload donne ensuite la main à la méthode ' end' de l'application.

Cette dernière méthode appelle la vue TT qui se chargera d'afficher le template interprété. Notre formulaire est maintenant affiché et le javascript chargé.

Après avoir renseigné le fichier à transférer, nous cliquons sur 'Envoyer'. C'est alors la méthode 'save' du controleur Upload qui est appelé. Après avoir sauvegardé le fichier dans '/tmp' elle se termine en transférant le contexte vers la méthode 'index' du controleur. Et c'est à nouveau l'affichage du formulaire.

Encore une chose mais qui a son importance. L'application doit être démarrée avec l'option 'fork' pour l'autoriser à forker le daemon. Cela est nécessaire pour l'affichage de la barre de progression dont l'Ajax doit ouvrir un canal http pour communiquer avec le serveur. Toutefois fois ce problème ne se pose pas lorsque l'application est exécuter en mode 'mod_perl' ou Fastcgi.

Lancement de l'application avec le mini serveur HTTP de Catalyst:

perl script/monapp_server.pl -f

Ce qui au final nous donne:

 ls -lrt /tmp/test.avi
-rw-r--r-- 1 dab dab 64233472 2007-08-28 18:09 /tmp/test.avi

Sympa non ?


Add a comment

Validator_logo
Catapulse v0.06
( 0.115403 s)