Manejo de archivos
Muchas aplicaciones necesitan trabajar con archivos.
Por ejemplo:
- subir imágenes
- subir documentos
- descargar archivos
- almacenar archivos en el servidor
Spring Boot facilita mucho este proceso.
En este capítulo veremos:
- subir archivos
- guardar archivos
- descargar archivos
- buenas prácticas
1. Subir archivos (Upload) #
Para subir archivos usamos:
1MultipartFile
Este objeto representa un archivo enviado desde el cliente.
2. Ejemplo HTML para subir archivo #
1<form method="post" enctype="multipart/form-data" action="/upload"> 2 3 <input type="file" name="file"> 4 <button type="submit">Subir</button> 5 6</form>
El atributo importante es:
1enctype="multipart/form-data"
3. Controller para subir archivo #
1@RestController 2public class FileController { 3 4 @PostMapping("/upload") 5 public String uploadFile(@RequestParam("file") MultipartFile file) { 6 7 return "Archivo recibido: " + file.getOriginalFilename(); 8 9 } 10 11}
4. Información disponible en MultipartFile #
Podemos obtener:
| método | función |
|---|---|
| getOriginalFilename() | nombre archivo |
| getSize() | tamaño |
| getContentType() | tipo MIME |
| getBytes() | contenido |
5. Guardar archivo en el servidor #
Normalmente guardamos el archivo en el sistema de archivos.
6. Ejemplo #
1@PostMapping("/upload") 2public String uploadFile(@RequestParam MultipartFile file) throws IOException { 3 4 Path path = Paths.get("uploads/" + file.getOriginalFilename()); 5 6 Files.write(path, file.getBytes()); 7 8 return "Archivo guardado"; 9 10}
Esto guardará el archivo en la carpeta:
1uploads
7. Crear carpeta automáticamente #
Podemos comprobar si la carpeta existe.
1Path uploadDir = Paths.get("uploads"); 2 3if(!Files.exists(uploadDir)) { 4 Files.createDirectories(uploadDir); 5}
8. Descargar archivos #
Para descargar archivos usamos ResponseEntity.
9. Ejemplo #
1@GetMapping("/download/{filename}") 2public ResponseEntity<Resource> downloadFile( 3 @PathVariable String filename) throws IOException { 4 5 Path path = Paths.get("uploads/" + filename); 6 7 Resource resource = new UrlResource(path.toUri()); 8 9 return ResponseEntity.ok() 10 .header(HttpHeaders.CONTENT_DISPOSITION, 11 "attachment; filename=\"" + filename + "\"") 12 .body(resource); 13 14}
10. Descargar archivos desde navegador #
Si visitamos:
1http://localhost:8080/download/documento.pdf
El navegador descargará el archivo.
11. Validar archivos subidos #
Siempre debemos validar los archivos.
Por ejemplo:
- tamaño máximo
- tipo de archivo
- nombre del archivo
12. Ejemplo validar tamaño #
1if(file.getSize() > 5_000_000) { 2 throw new RuntimeException("Archivo demasiado grande"); 3}
13. Validar tipo #
1if(!file.getContentType().equals("image/png")) { 2 throw new RuntimeException("Solo PNG permitido"); 3}
14. Configurar tamaño máximo #
En application.properties.
1spring.servlet.multipart.max-file-size=10MB 2spring.servlet.multipart.max-request-size=10MB
15. Guardar archivos con nombre único #
Para evitar conflictos se puede generar un nombre único.
16. Ejemplo #
1String filename = UUID.randomUUID() + "_" + file.getOriginalFilename();
Esto genera algo como:
13f2e91a2-foto.png
17. Guardar archivos en base de datos #
También podemos guardar archivos en la base de datos.
18. Ejemplo entidad #
1@Entity 2public class Document { 3 4 @Id 5 @GeneratedValue 6 private Long id; 7 8 private String name; 9 10 @Lob 11 private byte[] data; 12 13}
19. Guardar archivo #
1Document doc = new Document(); 2 3doc.setName(file.getOriginalFilename()); 4doc.setData(file.getBytes()); 5 6repository.save(doc);
20. Almacenamiento externo #
En aplicaciones grandes se usan servicios externos.
Ejemplos:
- Amazon S3
- Google Cloud Storage
- Azure Blob Storage
- Cloudinary
Esto evita cargar el servidor.
21. Buenas prácticas #
Validar archivos #
Nunca aceptar cualquier archivo.
Limitar tamaño #
Evita ataques de subida masiva.
Usar nombres únicos #
Evita sobrescribir archivos.
No guardar archivos en carpetas públicas #
Evita accesos no autorizados.
22. Ejemplo completo #
1@RestController 2@RequestMapping("/files") 3public class FileController { 4 5 private final Path uploadDir = Paths.get("uploads"); 6 7 @PostMapping("/upload") 8 public String upload(@RequestParam MultipartFile file) throws IOException { 9 10 if(!Files.exists(uploadDir)) { 11 Files.createDirectories(uploadDir); 12 } 13 14 String filename = UUID.randomUUID() + "_" + file.getOriginalFilename(); 15 16 Path path = uploadDir.resolve(filename); 17 18 Files.write(path, file.getBytes()); 19 20 return "Archivo guardado: " + filename; 21 22 } 23 24}
Resumen del tema
Conceptos clave #
- Carga de Archivos (
MultipartFile): recepción de archivos enviados mediante peticiones HTTPmultipart/form-datacon@RequestParam("file"). - Límites de Tamaño: configuración en properties (
spring.servlet.multipart.max-file-sizeymax-request-size) para prevenir ataques de denegación de servicio. - Almacenamiento en Disco: manipulación con la API moderna
java.nio.file.PathyFiles.copy()/Files.write(), asignando UUIDs aleatorios para evitar colisiones y path traversal. - Descarga y Streaming de Ficheros: uso de
UrlResourceoByteArrayResourceenvuelto enResponseEntity<Resource>con cabeceraContent-Disposition: attachment; filename="...". - Persistencia en Base de Datos vs Cloud: campos
@Lob byte[]para ficheros pequeños vs integración con Object Storage (Amazon S3, GCP Cloud Storage) para producción escalable.
Qué debes recordar #
Valida siempre tipo MIME y tamaño de MultipartFile, sanitiza los nombres con UUIDs y devuelve Resource con cabeceras Content-Disposition para descargas seguras.