dimanche 25 novembre 2012

Java Serveur App 11 : fichiers en base de données


Fichiers en base de données

Nous allons voir comment gérer des fichiers en base de données dans une application Java Web. Les différentes étapes sont:

  • Créer un modèle de données permettant de stocker des données binaires, sous forme d'un tableau d'octets.
  • Permettre d'écrire des fichiers dans ce modèle grâce à un téléversement de fichier.
  • Permettre de servir les fichiers stockés afin de les afficher, de les télécharger etc.



Modèle de données

La première partie consiste à mettre en place une entité permettant de stocker un fichier. Voici le code d'une entité classique permettant de stocker un fichier:


package com.deguet;

import javax.persistence.*;

@Entity
public class File {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;

 @Lob // inferred as binary because it is a byte[]
 private byte[] content;

 private String type;

 public int getId() {return id;}
 public void setId(int id) {this.id = id;}

 public byte[] getContent() {return content;}
 public void setContent(byte[] content) {this.content = content;}

 public String getType() {return type;}
 public void setType(String type) {this.type = type;}
 
}

Nous utilisons 2 champs de données : le premier est le contenu, la succession d'octets constituant le fichier, le second est le type de fichier.

File upload, téléversement de fichiers

Pour gérer le téléversement, la programmation web impose d'utiliser un formulaire envoyant ses paramètres selon la méthode POST (la méthode GET ne permet pas d'envoyer suffisamment de données). L'encodage des fichiers nécessite la déclaration de multipart dans le formulaire:



<form enctype="multipart/form-data" action="up" method="POST">
 Choose a file to upload: <input name="uploadedfile" type="file" /><br />
 <input type="submit" value="Upload" />
</form>

Pour la réception côté serveur du fichier, nous allons utiliser les utilitaires de la fondation Apache. Nous aurons besoin des deux dépendances suivantes:

<dependency>
 <groupId>commons-io</groupId>
 <artifactId>commons-io</artifactId>
 <version>2.4</version>
</dependency>

<dependency>
 <groupId>commons-fileupload</groupId>
 <artifactId>commons-fileupload</artifactId>
 <version>1.2.2</version>
</dependency>

La réception va se faire à travers un motif URL dans notre contrôleur.
if ( ServletFileUpload.isMultipartContent( request ))
{
 System.out.println("MultiPart might contain a file ");
 List<FileItem> fileItems;
 try {
  fileItems = new ServletFileUpload( new DiskFileItemFactory()).parseRequest( request );
  for ( FileItem item : fileItems )
  {
   String fieldName = item.getFieldName();
   if ( item.isFormField()) { 
    item.getString();      
    System.out.println("Param post multi not file " + fieldName+" = "+item.getString());
   } // Form's input field
   else { 
    System.out.println("Param post multi file " + fieldName+" = "+item.getContentType());
    File i = new File();
    // get the type
    i.setType(item.getContentType());
    // get the bytes
    i.setContent(item.get());
    // save it in database
    facade.create(i);
    response.sendRedirect("index.jsp");
    return;
   }
  }
 } catch (FileUploadException e) {
  e.printStackTrace();
 } catch (Throwable e) {
  e.printStackTrace();
 }
}
Quelques points sur le code précédent:
  • Il s'applique sur une requête MultiPart.
  • Apache FileUpload fonctionne avec des FileItem qui représentent les fichiers contenus dans la requête.
  • Les items peuvent être des "form fields", ce sont les champs classiques de formulaires qui se retrouvent sous la forme de chaîne de caractères.
  • Dans le cas contraire, c'est un fichier, autrement dit une succession d'octets.
  • La fonction get() de l'item permet de récupérer les octets du fichier, getContentType permet d'obtenir le type MIME.
  • Finalement, notre façade nous permet de créer le fichier récupéré.

Service d'accès à un fichier

Pour servir le fichier stocké en base de données, nous allons utiliser un motif URL qui va directement envoyer le fichier dans sa réponse HTTP. 
if (action.equals("/down")){
 System.out.println("Got a request for a file ");
 // get the image from the database
 String id = request.getParameter("id");
 Integer i = Integer.parseInt(id);
 File img = facade.find(i);
 // set the file type in headers
 response.setContentType(img.getType());
 // write the bytes directly to the response
 ServletOutputStream out = response.getOutputStream();
 byte[] bytes = img.getContent();
 out.write(bytes);
 return;
}


Fichiers du projet

Vous trouverez ici un projet illustrant le stockage de fichiers binaires dans une application web Java.




Aucun commentaire:

Enregistrer un commentaire