首页 > 解决方案 > java.lang.IllegalStateException: getWriter() 已经为此响应调用过,甚至认为它只调用过一次

问题描述

我正在使用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 只被调用一次。如何解决这个问题。

标签: spring-bootcsvservlet-3.0opencsv

解决方案


我发现了这个问题。问题是我在控制器中发送了一个字符串(一条消息)作为响应,但在服务中,我正在发送一个附件。所以 getWriter() 被我第一次在服务中调用,第二次被 spring 调用来编写字符串类型的响应消息。解决方法:我将控制器中方法的返回类型设置为voidex::

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

唯一的问题是,如果服务出现问题,您无法发送错误消息,并且还有其他替代方法可以克服它。


推荐阅读