【问题标题】:Unsuccessful content negotation with excel file与 excel 文件的内容协商不成功
【发布时间】:2021-03-09 18:59:01
【问题描述】:

我有一个 Spring Boot 应用程序,它的端点已经在工作,可以生成一个 xlsx 文件。 现在,我想在这个端点上实现内容协商,但我总是收到406 Not Acceptable

{
    "timestamp": "2021-03-09T18:44:56.997+0000",
    "status": 406,
    "error": "Not Acceptable",
    "message": "Could not find acceptable representation",
    "path": "/students/excel"
}

我正在使用 URL 参数,我这样称呼它

localhost:8080/students/excel/excel?format=xlsx

实现

端点

    @PostMapping(path = "/excel", produces = {"application/vnd.ms-excel"})
    public byte[] generateExcel(HttpServletResponse response, final @RequestBody @NonNull Criteria criteria) {
            
        response.setContentType("application/vnd.ms-excel");

        response.setHeader("Content-Disposition", "attachment; filename=Students.xlsx");

        return studentService.generateExcelReport(response, criteria);
    }

完成 excel 文件的方法。

   public static byte[] write(HttpServletResponse response, final @NonNull XSSFWorkbook workbook) {
        
        try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            os.writeTo(response.getOutputStream());
            workbook.write(os);
            workbook.close();
            return os.toByteArray();
        } catch (final IOException ex) {
            throw new RuntimeException("Error generating excel", ex);
        }
    }

以及实现WebMvcConfigurerWebConfiguration上的相关方法

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {

        configurer.favorPathExtension(false).
                        favorParameter(true).
                        parameterName("format").
                        ignoreAcceptHeader(true).
                        useJaf(false).
                defaultContentType(MediaType.APPLICATION_JSON).
                mediaType("xlsx", MediaType.MULTIPART_FORM_DATA);
    }

我尝试了很多与MediaTypeWebConfiguration 的组合以及produces 的属性,比如 application/csv 检查是否有可能由于 excel 文件和其他文件的格式化而起作用。但我无法克服这种状态。将其设置为 application/jsontext/plain 时,它可以工作,但它不是想要的功能或正确的功能。

当我不使用内容协商时,excel 的生成就像我提到的那样工作。

编辑: 根据建议,我将内容类型更改为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,并在Postman 上更改了AcceptContent-Type 的标头,仍然收到406

这就是 Postman 上的请求的样子

我也调试了应用程序,它没有进入端点的方法,它似乎因为产生的值而立即失败。

我想补充一点,这是一个接受 JSON 的 POST 请求。因此,在 Postman 上使用任何其他内容类型都会破坏它。

更新

它通过使用接受头而不是参数并更改WebConfigurer 方法来工作。但是,我想使用 URL 参数并了解它们为什么不起作用。

@Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(true).
                favorParameter(false).
                ignoreAcceptHeader(false).
                useJaf(false);
    }

【问题讨论】:

  • 您似乎忘记在通话中将 Accept 标头设置为 application/vnd.ms-excel
  • xslx 的内容类型是 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • 我尝试实施您的两个建议。 @Jens 我忘了提到这是我使用的第一个 Content-Type 并且现在阅读它是首选的 application/vnd.ms-excel 也许我错了,我在 @Seelenvirtuose 的建议下再次尝试了,遗憾的是我仍然收到406. 我将通过测试更新问题。我也很担心MediaType.MULTIPART_FORM_DATA,我完全不确定。
  • 您是否更改了produces和set cntenttype中的字符串?
  • @Jens 是的,我都有。

标签: java excel spring-boot content-negotiation media-type


【解决方案1】:

我找到了一个解决方案,以使其与 URL 参数一起工作,因为这是我的初衷。 我在WebConfiguration 上添加了vnd.ms-excel 的新媒体类型,如下所示。

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false).
                        favorParameter(true).
                        parameterName("format").
                        ignoreAcceptHeader(true).
                        useJaf(false).
                defaultContentType(MediaType.APPLICATION_JSON).
                mediaType("xlsx", new MediaType("application","vnd.ms-excel"));
    }

在请求的 Accept 标头上,我添加了值 application/vnd.ms-excel

最后,现在通过使用所需格式调用 excel 端点,它可以正确生成 excel 文件。

localhost:8080/students/excel/excel?format=xlsx

【讨论】:

    猜你喜欢
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多