Cómo guardar el archivo cargado en JSF
Estoy subiendo un archivo en JSF. Estoy usando Tomahawk <t:inputFileUpload>
para esto, pero la misma pregunta se aplica, por ejemplo, a PrimeFaces <p:fileUpload>
y JSF 2.2 <h:inputFile>
.
Tengo el siguiente código de bean de respaldo:
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();
}
Puedo obtener el nombre, el tipo y el tamaño del archivo, pero no puedo guardarlo en una ruta específica. No puedo encontrar la manera correcta de guardar el archivo cargado. ¿Cómo puedo conseguir esto?
El getInputStream()
método del archivo cargado representa el contenido del archivo.
InputStream input = uploadedFile.getInputStream();
Necesitas copiarlo a un archivo. Primero debe preparar una carpeta en el sistema de archivos del disco local donde se deben almacenar los archivos cargados. Por ejemplo /path/to/uploads
(en Windows, eso estaría en el mismo disco donde se ejecuta el servidor). Tenga en cuenta que no debe almacenar los archivos en la carpeta WAR expandida o incluso en la carpeta del proyecto IDE utilizando una ruta codificada o una ruta relativa a la web o getRealPath()
por los motivos mencionados aquí . La imagen cargada solo está disponible después de actualizar la página .
Luego, debes generar automáticamente el nombre del archivo. De lo contrario, cuando alguien cargue un archivo con el mismo nombre coincidentemente más adelante, se sobrescribirá. Puede utilizar Files#createTempFile()
la función para obtener un nombre de archivo generado automáticamente.
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);
La ruta de carga podría, si fuera necesario, parametrizarse según una de las varias formas que se muestran en estas preguntas y respuestas: Forma recomendada de guardar archivos cargados en una aplicación de servlet . Es FilenameUtils
parte de Apache Commons IO que ya debería tener en su classpath ya que es una dependencia del componente de carga de archivos Tomahawk.
Finalmente, simplemente transmita el archivo cargado a ese archivo (asumiendo Java 7):
try (InputStream input = uploadedFile.getInputStream()) {
Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
}
System.out.println("Uploaded file successfully saved in " + file);
Luego, para volver a descargarlo, lo más fácil sería registrarse /path/to/uploads
como un nuevo contexto de aplicación web o un host virtual para que todos esos archivos estén disponibles mediante una URL. Consulte también Cargar imágenes desde fuera de la carpeta webapps/webcontext/implementar usando la etiqueta <h:graphicImage> o <img> .
PrimeFaces utiliza dos decodificadores de carga de archivos para cargar contenido de p:fileupload
- NativeFileUploadDecodificador
- CommonsFileUploadDecodificador
NativeFileUploadDecoder es el decodificador de carga predeterminado y requiere el contenedor de servlets 3.0. Entonces, si su contenedor de servlets es inferior a 3, entonces no funcionará con usted. Además, algunos servidores de aplicaciones imponen restricciones sobre el uso de contenido de varias partes.
Entonces, si tiene un problema con el decodificador de carga nativo por cualquier motivo, debe usar el otro decodificador que es "CommonsFileUploadDecoder".
CommonsFileUploadDecoder depende de la biblioteca común de Apache, por lo que debe colocar los archivos jar commons-fileupload y commons-io en su class-path. La versión depende de su versión Primefaces, pero 1.3 y 2.2 respectivamente funcionan para mí.
para usar CommonsFileUploadDecoder tienes que usar filtro
<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>
espere, el filtro solo no funcionará porque dentro del filtro verifica el cargador si no se proporciona y detecta al menos JSF 2.2, por lo que omitirá la solicitud al decodificador predeterminado "Nativo" y luego tampoco funcionará para usted.
Para forzar que el filtro use el decodificador común, debe colocar el siguiente parámetro de contexto en su web.xml.
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value>
</context-param>