Implementación de Carga y Descarga de Archivos usando Streams en Java

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;
       

Etiquetas: java Spring Servlets File Upload File Download

Publicado el 9-5 14:35