web-dev-qa-db-fra.com

Comment enregistrer le fichier téléchargé dans JSF

Je télécharge un fichier au format JSF. J'utilise le <t:inputFileUpload> de Tomahawk pour cela, mais la même question s'applique par exemple à. PrimeFaces <p:fileUpload> et JSF 2.2 <h:inputFile>.

J'ai le code de haricot de soutien ci-dessous:

private UploadedFile uploadedFile; // +getter+setter

public String save() throws IOException {
    String name = uploadedFile.getName();
    System.out.println("File name: " + name);

    String type = uploadedFile.getContentType();
    System.out.println("File type: " + type);

    long size = uploadedFile.getSize();
    System.out.println("File size: " + size);  

    InputStream stream = uploadedFile.getInputStream();
    byte[] buffer = new byte[(int) size];  
    stream.read(buffer, 0, (int) size);  
    stream.close();  
}

Je peux obtenir le nom, le type et la taille du fichier, mais je ne peux pas enregistrer ce fichier sur un chemin spécifique. Je n'arrive pas à trouver le bon moyen de sauvegarder le fichier téléchargé. Comment puis-je atteindre cet objectif?

16
V.Rohan

La méthode getInputStream() du fichier téléchargé représente le contenu du fichier. 

InputStream input = uploadedFile.getInputStream();

Vous devez le copier dans un fichier. Vous devez d’abord préparer un dossier sur le système de fichiers du disque local où les fichiers téléchargés doivent être stockés. Par exemple, /path/to/uploads (sous Windows, ce serait sur le même disque que celui sur lequel le serveur est exécuté). Notez que vous devez absolument pas stocker les fichiers dans le dossier WAR étendu en utilisant un chemin relatif ou getRealPath() pour les raisons mentionnées ici Image téléchargée uniquement disponible après l'actualisation de la page .

Ensuite, vous devez générer automatiquement le nom de fichier. Sinon, si quelqu'un d'autre télécharge un fichier avec le même nom par la suite, il sera écrasé. Vous pouvez utiliser Files#createTempFile() facility pour obtenir un nom de fichier généré automatiquement. 

Path folder = Paths.get("/path/to/uploads");
String filename = FilenameUtils.getBaseName(uploadedFile.getName()); 
String extension = FilenameUtils.getExtension(uploadedFile.getName());
Path file = Files.createTempFile(folder, filename + "-", "." + extension);

Le chemin du téléchargement pourrait si nécessaire être paramétré en fonction de l’une des méthodes présentées dans ce Q & A: Méthode recommandée pour enregistrer les fichiers téléchargés dans une application de servlet . La FilenameUtils fait partie d'Apache Commons IO que vous devriez déjà avoir dans votre chemin de classe car il s'agit d'une dépendance du composant de téléchargement de fichier Tomahawk.

Enfin, diffusez simplement le fichier téléchargé dans ce fichier (en supposant que Java 7):

try (InputStream input = uploadedFile.getInputStream()) {
    Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
}

System.out.println("Uploaded file successfully saved in " + file);

Ensuite, pour le télécharger à nouveau, le plus simple serait d’enregistrer /path/to/uploads en tant que nouveau contexte d’application Web ou hôte virtuel afin que tous ces fichiers soient disponibles via une URL. Voir aussi Chargez des images en dehors du dossier webapps/webcontext/deploy en utilisant <h: graphicImage> ou la balise <img> .

52
BalusC

PrimeFaces utilise deux décodeurs de téléchargement de fichier pour télécharger le contenu de p: fileupload 

  1. NativeFileUploadDecoder
  2. CommonsFileUploadDecoder

NativeFileUploadDecoder est le décodeur de téléchargement par défaut et nécessite le conteneur de servlet 3.0. Donc, si votre conteneur de servlets est inférieur à 3, il ne fonctionnera pas avec vous. De plus, certains serveurs d’applications restreignent l’utilisation de contenu en plusieurs parties. 

Donc, si vous avez un problème avec le décodeur de téléchargement natif pour une raison quelconque, vous devez utiliser l'autre décodeur qui est "CommonsFileUploadDecoder"

CommonsFileUploadDecoder dépend de la librairie commune Apache Vous devez donc placer les jarres commons-fileupload et commons-io dans votre chemin de classe La version dépend de votre version de primefaces mais les versions 1.3 et 2.2 fonctionnent respectivement pour moi. .

pour utiliser CommonsFileUploadDecoder, vous devez utiliser un filtre 

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

attend que le filtre ne fonctionne pas car à l'intérieur du filtre, il vérifie si le programme de téléchargement n'est pas fourni et qu'il détecte au moins JSF 2.2, de sorte qu'il ignore la demande au décodeur par défaut "Native", puis ne fonctionne pas. pour toi aussi 

pour forcer le filtre à utiliser le décodeur commun, vous devez mettre le paramètre de contexte suivant dans votre web.xml

<context-param>
<param-name>primefaces.UPLOADER</param-name>
   <param-value>commons</param-value>
</context-param>
1
HMoussa