Saltar al contenido

descargue un archivo del servicio Spring Boot Rest

Entiende el código bien previamente a usarlo a tu proyecto y si tquieres aportar algo puedes compartirlo con nosotros.

Solución:

Opción 1 usando un InputStreamResource

Implementación de recursos para un InputStream determinado.

Solo debe ser usado si no hay otra implementación de Recurso específica > aplicable. En particular, prefiera ByteArrayResource o cualquiera de las implementaciones de recursos basadas en archivos cuando sea posible.

@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity download(String param) throws IOException 

    // ...

    InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

    return ResponseEntity.ok()
            .headers(headers)
            .contentLength(file.length())
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .body(resource);


Opcion 2 como sugiere la documentación de InputStreamResource, usando un ByteArrayResource:

@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity download(String param) throws IOException 

    // ...

    Path path = Paths.get(file.getAbsolutePath());
    ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));

    return ResponseEntity.ok()
            .headers(headers)
            .contentLength(file.length())
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .body(resource);

El siguiente código de muestra funcionó para mí y podría ayudar a alguien.

import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@RestController
@RequestMapping("/app")
public class ImageResource 

    private static final String EXTENSION = ".jpg";
    private static final String SERVER_LOCATION = "/server/images";

    @RequestMapping(path = "/download", method = RequestMethod.GET)
    public ResponseEntity download(@RequestParam("image") String image) throws IOException 
        File file = new File(SERVER_LOCATION + File.separator + image + EXTENSION);

        HttpHeaders header = new HttpHeaders();
        header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=img.jpg");
        header.add("Cache-Control", "no-cache, no-store, must-revalidate");
        header.add("Pragma", "no-cache");
        header.add("Expires", "0");

        Path path = Paths.get(file.getAbsolutePath());
        ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));

        return ResponseEntity.ok()
                .headers(header)
                .contentLength(file.length())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(resource);
    


Sugeriría usar un StreamingResponseBody ya que con él la aplicación puede escribir directamente en la respuesta (OutputStream) sin retrasar el subproceso del contenedor Servlet. Es un buen enfoque si está descargando un archivo muy grande.

@GetMapping("download")
public StreamingResponseBody downloadFile(HttpServletResponse response, @PathVariable Long fileId) 

    FileInfo fileInfo = fileService.findFileInfo(fileId);
    response.setContentType(fileInfo.getContentType());
    response.setHeader(
        HttpHeaders.CONTENT_DISPOSITION, "attachment;filename="" + fileInfo.getFilename() + """);

    return outputStream -> 
        int bytesRead;
        byte[] buffer = new byte[BUFFER_SIZE];
        InputStream inputStream = fileInfo.getInputStream();
        while ((bytesRead = inputStream.read(buffer)) != -1) 
            outputStream.write(buffer, 0, bytesRead);
        
    ;

Ps.: Al usar StreamingResponseBody, se recomienda encarecidamente configurar TaskExecutor utilizado en Spring MVC para ejecutar solicitudes asincrónicas. TaskExecutor es una interfaz que abstrae la ejecución de un Runnable.

Más información: https://medium.com/swlh/streaming-data-with-spring-boot-restful-web-service-87522511c071

Reseñas y puntuaciones del post

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *