2

I have a small problem which I've been unable to solve for a few hours. I am basically trying to stream an excel file from the resources folder withing a jar. The file has around 9KB in my file manager, however, when I download it by visiting the REST endpoint I receive a 13/14KB file which can no longer be opened by excel. The metadata is set correctly, as is the filename. I suspect the streaming/copying process is somehow corrupting the file. Here you may see the code snippet:


    public void getTemplateByDataType(HttpServletResponse response, DataType dataType) {

        String fileName = "excel_template.xlsx";
        String templateDirectory = "templates";

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");

        InputStream data = this.getClass().getClassLoader().getResourceAsStream(templateDirectory + "/" + fileName); // loading file from resources folder
        try {
            IOUtils.copy(data, response.getOutputStream()); // copying to httpservletresponse output stream
        } catch (IOException e) {
           //...    
        }
    }

I've already tried reading from a simple text file in the same location in order to verify whether the getResourceAsStream call works and this is the case. So I am somehow breaking something with the IOUtils.copy I guess? Does anybody have any suggestions why this simple code snippet breaks my xlsx files?

Just to get the full picture, the controller is relatively simple:

    @GetMapping(value = "/templates", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    public @ResponseBody
    void getFileTemplate(HttpServletResponse response,
            @ApiParam(value = "Type of data import", required = true) @RequestParam String dataType) {
        importService.getTemplateByDataType(response, DataType.fromValue(dataType));
    }
user13237363
  • 23
  • 1
  • 2

2 Answers2

0

Try Streaming Output. Maybe this would help you Example of using StreamingOutput as Response entity in Jersey

If you want to download as an attachment, then return the Response like below:

Response.status(Response.Status.OK)
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        String.format("attachment; filename=\"download.gz\""))
                .entity(streamingOutput)
                .build();

StreamingOutput streams the content of the file and at the client end, it will be downloaded as an attachment.

Suman
  • 818
  • 6
  • 17
  • I've tried that and unfortunately the same issue occurs. The file ends up being bigger than original and I can't open it. – user13237363 Aug 12 '20 at 10:02
  • No it works really good. I have done it with file content, compressing file content. Everything works fine. If I get time, I will try to draft some sample working code. I recommend you to try and share the issues you face. – Suman Aug 12 '20 at 10:42
0

try to copy this file directly to your output stream.

@GetMapping(value = "/templates", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    public @ResponseBody
    void getFileTemplate(HttpServletResponse response,
            @ApiParam(value = "Type of data import", required = true) @RequestParam String dataType) {
       
        String fileName = "excel_template.xlsx";
        String templateDirectory = "templates";
        Path templateFilePath = Paths.get(getClass().getClassLoader().getResource(templateDirectory + "/" + fileName).toURI());

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");

        try {
               FileCopyUtils.copy(new BufferedInputStream(new FileInputStream(templateFilePath.toFile())), response.getOutputStream());
               response.getOutputStream().flush();
               response.getOutputStream().close();
     } catch (IOException e) {
           //...    
        }
    }
    ```
L.G
  • 33
  • 10