Spring et Apache FileUpload

1. Vue d’ensemble

Https://commons.apache.org/proper/commons-fileupload/index.html[ Bibliothèque de téléchargement de fichiers Apache Commons ]nous aide à télécharger des fichiers volumineux sur le protocole HTTP à l’aide du type de contenu multipart/form-data .

Dans ce rapide tutoriel, nous allons voir comment l’intégrer à Spring.

2. Dépendances Maven

Pour utiliser la bibliothèque, nous avons besoin de l’artefact commons-fileupload :

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

La dernière version est disponible sur Maven Central .

3. Tout transférer d’un coup

À des fins de démonstration, nous allons créer un Controller traitant des demandes avec une charge de fichier:

@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setRepository(
      new File(System.getProperty("java.io.tmpdir")));
    factory.setSizeThreshold(
      DiskFileItemFactory.DEFAULT__SIZE__THRESHOLD);
    factory.setFileCleaningTracker(null);

    ServletFileUpload upload = new ServletFileUpload(factory);

    List items = upload.parseRequest(request);

    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();

        if (!item.isFormField()) {
            try (
              InputStream uploadedStream = item.getInputStream();
              OutputStream out = new FileOutputStream("file.mov");) {

                IOUtils.copy(uploadedStream, out);
            }
        }
    }
    return "success!";
}

Au début, nous devons vérifier si la demande contient un contenu en plusieurs parties en utilisant la méthode isMultipartContent trouvée dans la classe ServletFileUpload de la bibliothèque.

Par défaut, Spring comporte un MultipartResolver que nous devrons désactiver pour utiliser cette bibliothèque. Sinon, le contenu de la demande sera lu avant d’atteindre notre Controller.

Nous pouvons y parvenir en incluant cette configuration dans notre fichier application.properties:

spring.http.multipart.enabled=false

Maintenant, nous pouvons définir le répertoire dans lequel nos fichiers vont être enregistrés, le seuil dans lequel la bibliothèque décide d’écrire sur le disque et si des fichiers doivent être supprimés à la fin de la demande.

La bibliothèque fournit une classe DiskFileItemFactory qui __ assume la responsabilité de la configuration pour la sauvegarde et le nettoyage des fichiers .

La méthode setRepository définit le répertoire cible, la valeur par défaut étant affichée dans l’exemple.

Ensuite, le setSizeThreshold définit une taille de fichier maximale.

Ensuite, nous avons la méthode setFileCleaningTracker qui, lorsqu’elle est définie sur null, laisse les fichiers temporaires intacts. Par défaut, il les supprime une fois la demande terminée .

Nous pouvons maintenant continuer avec le traitement des fichiers.

Premièrement, nous créons notre ServletFileUpload en incluant notre usine précédemment créée; nous procédons ensuite à l’analyse de la demande et générons une liste de FileItem qui constituent l’abstraction principale de la bibliothèque pour les champs de formulaire.

Maintenant, si nous savons que ce n’est pas un champ de formulaire normal, alors nous allons extraire le InputStream et appeler la méthode de copie utile de IOUtils (pour plus d’options, vous pouvez jeter un oeil sur link: un fichier[ce]tutoriel) .

Nous avons maintenant notre fichier stocké dans le dossier nécessaire. C’est généralement un moyen plus pratique de gérer cette situation car il permet un accès facile aux fichiers, mais l’efficacité temps/mémoire n’est pas optimale.

Dans la section suivante, nous allons examiner l’API de diffusion en continu.

4. Streaming API

L’API de streaming est facile à utiliser, ce qui en fait un excellent moyen de traiter des fichiers volumineux simplement en ne les copiant pas dans un emplacement temporaire:

ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
    FileItemStream item = iterStream.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if (!item.isFormField()) {
       //Process the InputStream
    } else {
        String formFieldValue = Streams.asString(stream);
    }
}

Nous pouvons voir dans l’extrait de code précédent que nous n’incluons plus DiskFileItemFactory . En effet, lors de l’utilisation de l’API de streaming, nous n’en avons pas besoin .

Ensuite, pour traiter les champs, la bibliothèque fournit un FileItemIterator , qui ne lit rien avant de les extraire de la requête avec la méthode next .

Enfin, nous pouvons voir comment obtenir les valeurs des autres champs de formulaire.

5. Conclusion

Dans cet article, nous avons expliqué comment utiliser la bibliothèque de téléchargement de fichiers Apache Commons avec Spring pour télécharger et traiter des fichiers volumineux.

Comme toujours, le code source complet est disponible à l’adresse https://github.com/eugenp/tutorials/tree/master/spring-rest-simpleover sur GitHub].