java.lang.IllegalStateException:此响应已经被调用getWriter(),甚至认为它只被调用了一次

时间:2019-08-27 08:29:56

标签: spring-boot csv servlet-3.0 opencsv

我正在使用spring-boot。我想发送CSV作为响应的附件,为此我正在使用opencsv将Bean写入响应。即使response.getWriter()仅被调用一次,我也遇到了这个异常。

在寻找解决方案时,我知道我们不能同时使用response.getWriter()response.getOutputStream()。但这不是事实。

我只调用一次getWriter。

我还通过写一个普通字符串来检查它是否归因于opencsv库。 “名称,测试”。但是还是一样的错误。因此也不是因为opencsv

private Pair<Boolean, String> writeCSVToResponse(List<QuestionDownloadResponse> qdrList,  HttpServletResponse response) {
    String fileName = new SimpleDateFormat("'CSV'yyyyMMddHHmmss'.csv'").format(new Date());
    response.reset();
    response.setContentType("application/csv");
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
            "attachment; filename=\"" + fileName + "\"");
    response.setCharacterEncoding("UTF-8");
    //Find answer, for now we will return any if exists
    try {
        Writer writer = response.getWriter();
        // Create Mapping Strategy to arrange the  
        // column name in order 
        final CustomCSVMappingStrategy<QuestionDownloadResponse> mappingStrategy = new CustomCSVMappingStrategy<>();

        mappingStrategy.setType(QuestionDownloadResponse.class); 

        StatefulBeanToCsv<QuestionDownloadResponse> sbc = new StatefulBeanToCsvBuilder<QuestionDownloadResponse>(writer)
           .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
           .withMappingStrategy(mappingStrategy)
           .build();

        sbc.write(qdrList);

    } catch (IOException e) {
        CMSQuestionServiceImpl.logger.error("Error in CSV IO operations", e);
        return Pair.of(false, "Failed to Open file");
    } catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
        CMSQuestionServiceImpl.logger.error("Error in CSV Write operation", e);
        return Pair.of(false,"Failed to write in csv");
    }

}

为什么即使将response.getWriter恰好调用一次,也会出现此异常。如何解决这个问题。

1 个答案:

答案 0 :(得分:0)

我发现了问题。问题是我在控制器中作为响应发送了一个String(消息),但是在服务中,我正在发送附件。因此,我第一次在服务中调用了getWriter(),第二次在spring上调用了getWriter()以编写String类型的响应消息。解决方案:我在控制器中将方法的返回类型设置为void ex ::

@GetMapping(value = "/downloadCSV") public void downloadCSV(@RequestBody(required = false) List<Integer> items, HttpServletResponse response){

唯一的问题是,如果服务出现问题,您将无法发送错误消息,并且还有其他解决方法。