用excel文件内容协商不成功

问题描述

我有一个 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);
        }
    }

以及实现 WebConfigurationWebMvcConfigurer 上的相关方法

    @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 上的请求的样子

enter image description here

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

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

更新

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

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

解决方法

我找到了一个解决方案,使其能够使用 URL 参数,因为这是我的第一个意图。 我在 vnd.ms-excel 上添加了一个新的媒体类型 WebConfiguration,如下所示。

    @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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...