问题描述
我认为我的场景很常见.我有一个数据库,我希望我的 Spring MVC
应用程序接受控制器中的请求,调用数据库服务以获取数据并将该数据作为 CSV 文件发送到客户端.我正在使用此处找到的 JavaCSV
库来协助该过程:http://sourceforge.net/projects/javacsv/
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.
我认为将数据写入 HttpServletResponse
的 outputStream 就足够了,但显然我遗漏了一些东西.
I thought writing the data to the HttpServletResponse
's outputStream would be sufficient, but apparently, I'm missing something.
这是我的控制器代码:
@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.
推荐答案
好像是你的Content-type设置不正确,应该是response.setContentType("text/csv;charset=utf-8")
而不是 response.setContentType("data:text/csv;charset=utf-8")
.
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")
.
此外,如果您使用的是 Spring 3,您可能应该使用 @ResponseBody HttpMessageConverter 用于代码重用.例如:
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");
}
加上一个简单的HttpMessageConverter:
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 控制器以将文件发送到客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!