gpt4 book ai didi

java - Spring内容协商/OpenCSV : Getting a blank CSV

转载 作者:太空宇宙 更新时间:2023-11-04 06:50:22 25 4
gpt4 key购买 nike

我正在使用 Spring 的内容协商和 OpenCSV 将 CSV 文件输出到客户端。

所以我有这个 Controller :

@RequestMapping(value = { "", "/" }, method = RequestMethod.GET, produces = "text/csv")
@esponseStatus(HttpStatus.OK)
public Model getCustomersView(HttpServletRequest request, Model model)
throws InvalidBusinessContractDataException {
Customer[] customers = customerService.findCustomers();
return model.addAttribute("customers", customers);
}

这个媒体类型转换器:

@Component("viewNameTranslator")
public final class MediaTypeRequestToViewTranslator implements
RequestToViewNameTranslator {
@Autowired
private ContentNegotiationManager contentNegotiationManager;

private DefaultRequestToViewNameTranslator defaultTranslator = new DefaultRequestToViewNameTranslator();

// a list of media types to ignore - not output on the translated view
private List<String> ignoredTypes = Arrays.asList("text/html");

@Override
public String getViewName(HttpServletRequest request) {
// first resolve the media type (see below)
String mediaType = resolveMediaType(request);

// delegate to the default translator to get the view name
String viewName = defaultTranslator.getViewName(request);

// concatenate the resolved media type to the default name and return it
return viewName + mediaType;
}

private String resolveMediaType(HttpServletRequest request) {
try {
// use the content negotiation manager to resolve the media type
// from the request. The manager does it
// according to its own search path and preferences - using the
// suffix, using the Accept header and
// preferring one of them. The result would always be a single type
// or none at all, but it returns a list
List<MediaType> types = contentNegotiationManager
.resolveMediaTypes(new ServletWebRequest(request));

// resolve to a single type
String type = types == null || types.size() == 0 ? "" : types
.get(0).toString();

// if it's not in the ignored media types - prepend a semi-colon and
// return it
return ignoredTypes.contains(type) ? "" : ";" + type;
} catch (HttpMediaTypeNotAcceptableException e) {
return "";
}
}
}

这个 View :

@Component("customers;text/csv")
public final class CustomerCsvView implements View {
@Override
public String getContentType() {
return "text/csv";
}

@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.setContentType("text/csv");
Customer[] customers = (Customer[]) model.get("customers");


CSVWriter writer = new CSVWriter(new OutputStreamWriter(response
.getOutputStream()));

writer.writeNext(new String[] {"id", "fName", "lName"});
for (Customer c : customers) {
System.out.println("FOO");
writer.writeNext(new String[] {
new Long(c.getCustomerId()).toString(), c.getFirstName(), c.getLastName() });
}
}
}

当我用浏览器点击这个 Controller 时,“FOO”在我的控制台中出现两次,弹出一个文件保存对话框,其中包含要下载的 test/csv 文件,并且它是 0 字节。

就像对响应的更改没有保留一样。

怎么了?

最佳答案

在发送数据之前设置内容类型并刷新数据,然后关闭outputwriter

response.setContentType("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);

// write data in csvwrite in loop

最后关闭flush就关闭了。

outputwriter.flush();   
outputwriter.close();
<小时/>

如果使用 @ResponseBody 会更好HttpMessageConverter与 Spring 3.0

在你的 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:

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();
}
}

要绑定(bind)的简单对象

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;
}
}

关于java - Spring内容协商/OpenCSV : Getting a blank CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23374518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com