配置Spring MVC控制器将文件发送到客户端 [英] Configuring Spring MVC controller to send file to client
问题描述
我认为我的情况很常见。我有一个数据库,我想我的Spring MVC应用程序接受控制器中的请求,调用DB服务获取数据,并将该数据作为CSV文件发送到客户端。我正在使用这里找到的JavaCSV库来协助处理: http://sourceforge.net/projects/javacsv /
我发现了几个人做类似事情的例子,并将一些看起来正确的东西拼凑在一起。
我认为将数据写入HttpServletResponse的outputStream就足够了,但显然我错过了一些东西。 / p>
这是我的控制器代码:
@RequestMapping(value =/ getFullData.html,method = RequestMethod.GET)
public void getFullData(HttpSession会话,HttpServletRequest请求,HttpServletResponse响应)throws IOException {
List< CompositeRequirement> allRecords = compReqServ.getFullDataSet((String)session.getAttribute(currentProject));
response.setContentType(data:text / csv; charset = utf-8);
OutputStream resOs = response.getOutputStream();
OutputStream buffOs =
response.setHeader(Content-Disposition,attachment; filename = \yourData.csv \ new BufferedOutputStream(resOs);
OutputStreamWriter outputwriter = new OutputStreamWriter(buffOs);
CsvWriter writer = new CsvWriter(outputwriter,'\\\ ');
for = 1; i CompositeRequirement aReq = allRecords.get(i);
writer.write(aReq.toString());
}
outputwriter.flush();
outputwriter.close();
};
我在这里缺少什么步骤?基本上,净效果是什么,我会想到设置标题和内容类型会导致我的浏览器拿起响应和触发下载动作。
这似乎是因为您的Content类型设置不正确,应该 response.setContentType(text / csv; charset = utf-8)
而不是 response.setContentType
此外,如果您使用的是Spring 3,您应该使用 @ ResponseBody HttpMessageConverter 代码重用。例如:
-
在控制器中:
@RequestMapping(value =/getFullData2.html,method = RequestMethod.GET,consumes =text / csv)
@ResponseBody //表示使用兼容的HttpMessageConverter
public CsvResponse getFullData(HttpSession session)throws IOException {
List< CompositeRequirement> allRecords = compReqServ.getFullDataSet((String)session.getAttribute(currentProject));
return new CsvResponse(allRecords,yourData.csv);
}
-
加上一个简单的HttpMessageConverter:
public class CsvMessageConverter extends AbstractHttpMessageConverter< CsvResponse> {
public static final MediaType MEDIA_TYPE = new MediaType(text,csv,Charset.forName(utf-8));
public CsvMessageConverter(){
super(MEDIA_TYPE);
}
protected boolean supports(Class<?> clazz){
return CsvResponse.class.equals(clazz);
}
protected void writeInternal(CsvResponse响应,HttpOutputMessage输出)throws IOException,HttpMessageNotWritableException {
output.getHeaders()。setContentType(MEDIA_TYPE);
output.getHeaders()。set(Content-Disposition,attachment; filename = \+ response.getFilename()+\);
OutputStream out = output.getBody();
CsvWriter writer = new CsvWriter(new OutputStreamWriter(out),'\\\ ');
List< CompositeRequirement> allRecords = response.getRecords();
for(int i = 1; i< allRecords.size(); i ++){
CompositeRequirement aReq = allRecords.get(i);
writer.write(aReq.toString());
}
writer.close();
}
}
-
:
public class CsvResponse {
private final String filename;
private final List< CompositeRequirement>记录;
public CsvResponse(List< CompositeRequirement> records,String filename){
this.records = records;
this.filename = filename;
}
public String getFilename(){
return filename;
}
public List< CompositeRequirement> getRecords(){
return records;
}
}
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 fle download action.
It seems to be because your Content-type is set incorrectly, it should be response.setContentType("text/csv;charset=utf-8")
instead of response.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:
@RequestMapping(value = "/getFullData2.html", method = RequestMethod.GET, consumes = "text/csv") @ResponseBody // indicate to use a compatible HttpMessageConverter public CsvResponse getFullData(HttpSession session) throws IOException { List<CompositeRequirement> allRecords = compReqServ.getFullDataSet((String) session.getAttribute("currentProject")); return new CsvResponse(allRecords, "yourData.csv"); }
plus a simple HttpMessageConverter:
public class CsvMessageConverter extends AbstractHttpMessageConverter<CsvResponse> { public static final MediaType MEDIA_TYPE = new MediaType("text", "csv", Charset.forName("utf-8")); public CsvMessageConverter() { super(MEDIA_TYPE); } protected boolean supports(Class<?> clazz) { return CsvResponse.class.equals(clazz); } protected void writeInternal(CsvResponse response, HttpOutputMessage output) throws IOException, HttpMessageNotWritableException { output.getHeaders().setContentType(MEDIA_TYPE); output.getHeaders().set("Content-Disposition", "attachment; filename=\"" + response.getFilename() + "\""); OutputStream out = output.getBody(); CsvWriter writer = new CsvWriter(new OutputStreamWriter(out), '\u0009'); List<CompositeRequirement> allRecords = response.getRecords(); for (int i = 1; i < allRecords.size(); i++) { CompositeRequirement aReq = allRecords.get(i); writer.write(aReq.toString()); } writer.close(); } }
and a simple object to bind everything together:
public class CsvResponse { private final String filename; private final List<CompositeRequirement> records; public CsvResponse(List<CompositeRequirement> records, String filename) { this.records = records; this.filename = filename; } public String getFilename() { return filename; } public List<CompositeRequirement> getRecords() { return records; } }
这篇关于配置Spring MVC控制器将文件发送到客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!