File Download Implementation and Best Practices in Spring Boot REST Services

Nov 20, 2025 · Programming · 12 views · 7.8

Keywords: Spring Boot | File Download | REST Services | InputStreamResource | ByteArrayResource

Abstract: This article provides an in-depth exploration of various methods for implementing file downloads in Spring Boot REST services, focusing on the usage scenarios and performance differences between InputStreamResource and ByteArrayResource. By comparing issues in the original code with improved solutions, it explains key technical aspects including HTTP response header configuration, resource type selection, and cache control, offering developers a comprehensive file download solution.

Introduction

File download functionality is a common requirement in modern web applications. While Spring Boot framework provides robust support for REST services, special attention is needed when implementing file downloads, particularly in resource handling and HTTP response configuration. This article analyzes implementation principles and best practices based on real-world development challenges.

Analysis of Original Code Issues

In the original implementation, the developer used InputStreamReader as the response body, which caused file download failures. Main issues include:

Original code example:

@RequestMapping(path="/downloadFile",method=RequestMethod.GET)
    @Consumes(MediaType.APPLICATION_JSON_VALUE)
    public  ResponseEntity<InputStreamReader> downloadDocument(
                String acquistionId,
                String fileType,
                Integer expressVfId) throws IOException {
        File file2Upload = new File("C:\\Users\\admin\\Desktop\\bkp\\1.rtf");
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        InputStreamReader i = new InputStreamReader(new FileInputStream(file2Upload));
        System.out.println("The length of the file is : "+file2Upload.length());

        return ResponseEntity.ok().headers(headers).contentLength(file2Upload.length())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(i);
        }

Solution Using InputStreamResource

InputStreamResource is a resource implementation class provided by the Spring framework, specifically designed for wrapping input streams. This class should be used when no other specific resource implementation is applicable.

Improved code implementation:

@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String param) throws IOException {
    File file = new File("path/to/your/file");
    
    HttpHeaders headers = new HttpHeaders();
    headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
    headers.add("Pragma", "no-cache");
    headers.add("Expires", "0");
    headers.add("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");

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

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

Key improvements:

Optimized Solution Using ByteArrayResource

According to Spring official documentation recommendations, when file size is manageable, prefer ByteArrayResource or other file-based resource implementations.

Optimized code implementation:

@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String param) throws IOException {
    File file = new File("path/to/your/file");
    
    HttpHeaders headers = new HttpHeaders();
    headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
    headers.add("Pragma", "no-cache");
    headers.add("Expires", "0");
    headers.add("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");

    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);
}

Advantages analysis:

Detailed HTTP Header Configuration

Proper HTTP header configuration is crucial for file download functionality:

Performance Considerations and Best Practices

When selecting resource types, consider the following factors:

Conclusion

Through this analysis, we understand the correct methods for implementing file downloads in Spring Boot REST services. The key lies in selecting appropriate resource types and properly configuring HTTP response headers. Both InputStreamResource and ByteArrayResource have their respective application scenarios, and developers should choose based on specific requirements. Proper implementation not only resolves download failure issues but also provides better user experience and system performance.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.