spring boot - generating large csv file drops Content-Type and Content-Disposition headers

Viewed 733

Controller action generates CSV content and returns it with header Content-Disposition: attachment; filename=file.csv

    @GetMapping("/csv")
    public void csvEmissions(HttpServletResponse response) {
        try {

            ColumnPositionMappingStrategy<CsvRow> mapStrategy
                    = new ColumnPositionMappingStrategy<>();
            mapStrategy.setType(CsvRow.class);

            String[] columns = new String[]{
                    "col1",
                    "col2"
            };
            mapStrategy.setColumnMapping(columns);

            CSVWriter csvWriter = new CSVWriter(response.getWriter());

            StatefulBeanToCsv<CsvRow> btcsv = new StatefulBeanToCsvBuilder<CsvRow>(response.getWriter())
                    .withMappingStrategy(mapStrategy)
                    .withSeparator(',')
                    .build();

            btcsv.write(csvrows());

            response.setContentType("text/csv");
            response.setHeader("Content-Disposition", "attachment; filename=file.csv");
            csvWriter.close();
        } catch (IOException | CsvRequiredFieldEmptyException | CsvDataTypeMismatchException e) {
            throw new RuntimeException(e.getMessage());
        }

    }

all works fine when there is not much CsvRow returned by csvrows() method. File is properly downloaded by the browser.

When rows count is larger (let's say over 200) it drops Content-Type and Content-Disposition header and browser prints CSV output as a text in the browser.

Only Transfer-Encoding: chunked header is present in the response.

Any suggestions how to make it downloadable for large amount of data?

1 Answers

Header Content-Length is missing from your response that's why large content is being fetched into chunks and browser displays into tab.

To get the content length try saving csv data into temporary file before putting it to response. Also set the headers before writing data to response writer.

File file = createTempCSVFile();

response.setContentType("text/csv");
response.setContentLength((int)file.length());
response.setHeader("Content-Disposition", "attachment; filename=file.csv");

// write file data to response.getWriter();

Hope this helps!

Related