Download large file through spring mvc controller

2019-08-20 12:06发布

问题:

I have controller method that starts downloading file once user click "Download" button. List of Objects can contain large amount of objects up to 400 000. When I put in csv file small amount of objects - it works fine .

@RequestMapping(value = "/downloadCSV")
	public void downloadCSV(HttpServletResponse response) throws IOException 
	{
	
		response.setContentType("text/csv");
		String reportName = "metrics.csv";
		response.setHeader("Content-disposition", "attachment;filename="+reportName);
 
		ArrayList<String> rows = new ArrayList<String>();
		rows.add("A, B, C, D, E");
		rows.add("\n");
 
		for (int i = 0; i < someList.size(); i++) {
			String row = metricsDownloadModelList.get(i).getContentId() 
					+ someList.get(i).getA() + ", "
					+ someList.get(i).getB() + ", "
					+ someList.get(i).getC() + ", "
					+ someList.get(i).getD() + ", "
					+ someList.get(i).getE()
					+ "\n";
			rows.add(row);
		}
 
		Iterator<String> iter = rows.iterator();
		while (iter.hasNext()) {
			String outputString = (String) iter.next();
			response.getOutputStream().print(outputString);
		}
 
		response.getOutputStream().flush();

	}

But when I'm increasing the number of object in list to 1000 or more, it . give me an error:

Error executing a controller { org.apache.coyote.http11.HeadersTooLargeException: An attempt was made to write more data to the response headers than there was room available in the buffer. Increase maxHttpHeaderSize on the connector or write less data into the response headers.

Can I solve my problem without modifying my servlet config file? Is there any other approach to solve this problem?

回答1:

In order to download the file I would do the following:

  • create a temp CSV file
  • download the file

In order to do it I would write this kind of controller:

@RequestMapping(method = { RequestMethod.GET }, value = { "/downloadCsv" })
public ResponseEntity<InputStreamResource>  downloadCSV()
{
    try
    {
            String fileName = "test.csv";
            //Create here your CSV file
            File theCsv = new File(fileName);
            HttpHeaders respHeaders = new HttpHeaders();
            MediaType mediaType = new MediaType("text","csv");
            respHeaders.setContentType(mediaType);
            respHeaders.setContentDispositionFormData("attachment", fileName);
            InputStreamResource isr = new InputStreamResource(new FileInputStream(theCsv));
            return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
    }
    catch (Exception e)
    {
        String messagge = "Error in CSV creation; "+e.getMessage();
        logger.error(messagge, e);
        return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

By using this kind of controller I'm able in downloading very huge files

Angelo