与 excel 文件的内容协商失败
Unsuccessful content negotation with excel file
我有一个 Spring 引导应用程序,它有一个已经可以生成 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);
}
}
以及 WebConfiguration
上实现 WebMvcConfigurer
的相关方法
@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);
}
我尝试了很多 MediaType
和 WebConfiguration
的组合以及 produces
的属性,比如
application/csv
检查是否有可能由于 excel 文件和其他文件的格式而工作。但是我无法克服这种状态。将其设置为 application/json
和 text/plain
时它可以工作,但它不是所需的功能或正确的功能。
当我不使用内容协商时,excel 的生成就像我提到的那样工作。
编辑:
根据建议,我将内容类型更改为 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
并在 Postman 上更改了 Accept
和 Content-Type
的 header 并且仍然收到 406
.
这是 Postman 上的请求的样子
我也调试了应用程序,它没有进入端点的方法,它似乎因为生成值而立即失败。
我想补充一点,这是一个接受 JSON 的 POST 请求。因此,在 Postman 上使用任何其他 content-type 都会破坏它。
更新
它通过使用接受 header 而不是参数并更改 WebConfigurer
方法来工作。但是,我想使用 URL 参数并了解为什么它们不起作用。
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(true).
favorParameter(false).
ignoreAcceptHeader(false).
useJaf(false);
}
我找到了一个解决方案,使其可以使用 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
header 上,我添加了值 application/vnd.ms-excel
。
最后,现在通过使用所需格式调用 excel 端点,它可以正确生成 excel 文件。
localhost:8080/students/excel/excel?format=xlsx
我有一个 Spring 引导应用程序,它有一个已经可以生成 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);
}
}
以及 WebConfiguration
上实现 WebMvcConfigurer
@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);
}
我尝试了很多 MediaType
和 WebConfiguration
的组合以及 produces
的属性,比如
application/csv
检查是否有可能由于 excel 文件和其他文件的格式而工作。但是我无法克服这种状态。将其设置为 application/json
和 text/plain
时它可以工作,但它不是所需的功能或正确的功能。
当我不使用内容协商时,excel 的生成就像我提到的那样工作。
编辑:
根据建议,我将内容类型更改为 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
并在 Postman 上更改了 Accept
和 Content-Type
的 header 并且仍然收到 406
.
这是 Postman 上的请求的样子
我也调试了应用程序,它没有进入端点的方法,它似乎因为生成值而立即失败。
我想补充一点,这是一个接受 JSON 的 POST 请求。因此,在 Postman 上使用任何其他 content-type 都会破坏它。
更新
它通过使用接受 header 而不是参数并更改 WebConfigurer
方法来工作。但是,我想使用 URL 参数并了解为什么它们不起作用。
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(true).
favorParameter(false).
ignoreAcceptHeader(false).
useJaf(false);
}
我找到了一个解决方案,使其可以使用 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
header 上,我添加了值 application/vnd.ms-excel
。
最后,现在通过使用所需格式调用 excel 端点,它可以正确生成 excel 文件。
localhost:8080/students/excel/excel?format=xlsx