I think my scenario is pretty common. I have a database and I want my Spring MVC
app to accept a request in the controller, invoke the DB service to get data and send that data to the client as a CSV file. I'm using the JavaCSV
library found here to assist in the process: http://sourceforge.net/projects/javacsv/
I've found several examples of people doing similar things and cobbled together something that looks correct-ish. When I hit the method, though, nothing is really happening.
I thought writing the data to the HttpServletResponse
's outputStream would be sufficient, but apparently, I'm missing something.
Here's my controller code:
@RequestMapping(value="/getFullData.html", method = RequestMethod.GET)
public void getFullData(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws IOException{
List<CompositeRequirement> allRecords = compReqServ.getFullDataSet((String)session.getAttribute("currentProject"));
response.setContentType("data:text/csv;charset=utf-8");
response.setHeader("Content-Disposition","attachment; filename=\yourData.csv\"");
OutputStream resOs= response.getOutputStream();
OutputStream buffOs= new BufferedOutputStream(resOs);
OutputStreamWriter outputwriter = new OutputStreamWriter(buffOs);
CsvWriter writer = new CsvWriter(outputwriter, '\u0009');
for(int i=1;i <allRecords.size();i++){
CompositeRequirement aReq=allRecords.get(i);
writer.write(aReq.toString());
}
outputwriter.flush();
outputwriter.close();
};
What step am I missing here? Basically, the net effect is... nothing. I would have thought setting the header and content type would cause my browser to pick up on the response and trigger a file download action.
It seems to be because your Content-type is set incorrectly, it should be
response.setContentType("text/csv;charset=utf-8")
instead ofresponse.setContentType("data:text/csv;charset=utf-8")
.Additionally, if you are using Spring 3, you should probably use a @ResponseBody HttpMessageConverter for code reuse. For example:
In the controller:
plus a simple HttpMessageConverter:
and a simple object to bind everything together:
Based on Pierre answer, i did a converter. Here is the full code, that works with any Object passed:
TsvMessageConverter.java
TsvResponse.java
And on SpringContext.xml add the following:
So, you can use on your controller like this: