Define la ruta donde se almacenarán los archivos. Puedes ajustarla según tu entorno de desarrrollo o producción.
private static final String DIRECTORIO_ARCHIVOS = "D:/archivos_almacenados/"; // Rutas para pruebas locales
// private static final String DIRECTORIO_ARCHIVOS = "/var/almacenamiento/"; // Rutas para servidores
Nota importante: Para las clases del controlador, asegúrate de usar la anotación @Controller en lugar de @RestController.
Método para Subir Archivos
Este método maneja la lógica para recibir y guardar un archivo enviado desde el cliante.
/**
* Maneja la subida de un archivo.
* @param archivo El archivo adjunto recibido.
* @param peticion La solicitud HTTP entrante.
* @param respuesta La respuesta HTTP saliente.
*/
@RequestMapping(value = "/subirArchivo", method = RequestMethod.POST, produces = "text/html; charset=UTF-8")
public void manejarSubidaArchivo(MultipartFile archivo, HttpServletRequest peticion, HttpServletResponse respuesta) {
Map<String, Object> resultado = new HashMap<>();
resultado.put("estado", "fallido");
resultado.put("datos", null);
try {
if (archivo == null || archivo.isEmpty()) {
System.out.println("==== El archivo subido está vacío ====");
resultado.put("estado", "archivo vacío");
respuesta.setContentType("text/html; charset=UTF-8");
UtilidadesJson.escribirAJson(respuesta.getWriter(), resultado);
return;
}
String nombreOriginal = archivo.getOriginalFilename();
String extension = nombreOriginal.substring(nombreOriginal.lastIndexOf("."));
String identificadorUnico = UUID.randomUUID().toString().replace("-", "");
String nombreArchivoNuevo = identificadorUnico + extension;
File destinoArchivo = new File(DIRECTORIO_ARCHIVOS + nombreArchivoNuevo);
// Asegurar que el directorio padre exista
if (!destinoArchivo.getParentFile().exists()) {
destinoArchivo.getParentFile().mkdirs();
}
archivo.transferTo(destinoArchivo);
System.out.println("==== Archivo subido exitosamente ====");
resultado.put("estado", "exitoso");
resultado.put("datos", nombreArchivoNuevo);
respuesta.setContentType("text/html; charset=UTF-8");
UtilidadesJson.escribirAJson(respuesta.getWriter(), resultado);
} catch (IOException e) {
System.err.println("==== Error al subir el archivo ====");
e.printStackTrace();
resultado.put("estado", "error de IO");
try {
respuesta.setContentType("text/html; charset=UTF-8");
UtilidadesJson.escribirAJson(respuesta.getWriter(), resultado);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
Método para Descargar Archivos
Este método facilita la descarga de un archivo específico.
/**
* Maneja la descarga de un archivo.
* @param peticion La solicitud HTTP entrante.
* @param respuesta La respuesta HTTP saliente.
*/
@RequestMapping(value = "/descargarArchivo", method = RequestMethod.GET, produces = "text/html; charset=UTF-8")
public void manejarDescargaArchivo(HttpServletRequest peticion, HttpServletResponse respuesta) {
String nombreArchivoDescargar = peticion.getParameter("nombreArchivo");
String rutaCompleta = DIRECTORIO_ARCHIVOS + nombreArchivoDescargar;
System.out.println("== Ruta del archivo a descargar: " + rutaCompleta + " ==");
File archivoADescargar = new File(rutaCompleta);
OutputStream flujoSalida = null;
FileInputStream flujoEntrada = null;
try {
if (archivoADescargar.exists()) {
flujoEntrada = new FileInputStream(archivoADescargar);
// Configurar la respuesta para la descarga
String agenteUsuario = peticion.getHeader("user-agent");
if (agenteUsuario != null && agenteUsuario.toLowerCase().contains("firefox")) {
nombreArchivoDescargar = new String(nombreArchivoDescargar.getBytes("UTF-8"), "iso-8859-1");
} else {
nombreArchivoDescargar = URLEncoder.encode(nombreArchivoDescargar, "UTF-8");
}
respuesta.setHeader("Content-disposition", "attachment; filename=" + nombreArchivoDescargar);
flujoSalida = respuesta.getOutputStream();
byte[] buffer = new byte[4096];
int bytesLeidos;
while ((bytesLeidos = flujoEntrada.read(buffer)) != -1) {
flujoSalida.write(buffer, 0, bytesLeidos);
}
} else {
System.err.println("==== El archivo no existe: " + rutaCompleta + " ====");
respuesta.sendError(HttpServletResponse.SC_NOT_FOUND, "Archivo no encontrado");
}
} catch (IOException e) {
System.err.println("==== Error durante la descarga del archivo ====");
e.printStackTrace();
try {
respuesta.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error en el servidor");
} catch (IOException ioException) {
ioException.printStackTrace();
}
} finally {
try {
if (flujoSalida != null) {
flujoSalida.close();
}
if (flujoEntrada != null) {
flujoEntrada.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Clase de Utilidad para JSON
Esta clase auxiliar ayuda a serializar objetos a formato JSON para la comunicación entre el servidor y el cliente.
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.Writer;
public class UtilidadesJson {
private static final ObjectMapper mapeador = new ObjectMapper();
/**
* Convierte un objeto Java a una cadena JSON y la escribe en un Writer.
* @param escritor El Writer donde se escribirá el JSON.
* @param objeto El objeto a serializar.
*/
public static void escribirAJson(Writer escritor, Object objeto) {
try {
mapeador.writeValue(escritor, objeto);
} catch (JsonProcessingException e) {
System.err.println("Error al procesar JSON: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Error de IO al escribir JSON: " + e.getMessage());
e.printStackTrace();
}
}
}
Dependencias Necesarias (Imports)
Asegúrate de tener las siguientes importaciones en tus clases de controlador y utilidad.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;