【发布时间】:2018-09-01 12:15:29
【问题描述】:
TL:DR
我们如何覆盖 Spring 4.3+ 的当前行为,该行为强制对 HEAD 请求使用 RequestMethod.GET 或 @GetMapping,以便我们可以返回 Content-Length 标头而无需将所有数据写入响应 OutputStream?
加长版:
我刚刚注意到 Spring 改变了默认处理 GET/HEAD 请求的方式:
HTTP 头,选项
@GetMapping — 还有@RequestMapping(method=HttpMethod.GET),支持 HTTP HEAD 透明地用于请求映射目的。控制器 方法不需要改变。一个响应包装器,应用于 javax.servlet.http.HttpServlet,确保“Content-Length”标头是 设置为写入的字节数,而不实际写入 回应。
@GetMapping — 还有@RequestMapping(method=HttpMethod.GET),都是 隐式映射到并且还支持 HTTP HEAD。 HTTP HEAD 请求 像 HTTP GET 一样处理,但不是写 body、字节数和“Content-Length”标头 设置。
默认情况下,HTTP OPTIONS 通过设置“允许”响应来处理 标头到所有 @RequestMapping 中列出的 HTTP 方法列表 具有匹配 URL 模式的方法。
对于没有 HTTP 方法声明的 @RequestMapping,“允许” 标头设置为“GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS”。控制器 方法应始终声明支持的 HTTP 方法,例如 通过使用 HTTP 方法特定的变体 — @GetMapping, @PostMapping 等
@RequestMapping 方法可以显式映射到 HTTP HEAD 和 HTTP OPTIONS,但在一般情况下这不是必需的。
来源:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-head-options
https://stackoverflow.com/a/45412434/42962
我们如何覆盖这个默认行为,以便我们可以自己处理 HEAD 响应并设置 Content-Length 标头?
我们希望这样做,因为我们通过 Web 应用程序处理大文件(考虑超过 10 gigs 的大小),如果可能,我们希望不必将所有字节读入 Response 的 OutputStream。
这是我们当前代码的示例。只有第二种方法(带有 RequestMethod.GET 的 handleRequest)被调用。
@RequestMapping(value = "/file/{fileName:.+}", method = RequestMethod.HEAD)
public void handleHeadRequest(@RequestParam(value = "fileName") String fileName, HttpServletRequest request, HttpServletResponse response) {
File file = fileRepository.getFileByName(fileName)
response.addHeader("Accept-Ranges", "bytes");
response.addDateHeader("Last-Modified", file.lastModified());
Long fileSize = file.length();
response.addHeader(HttpHeaderConstants.CONTENT_LENGTH, fileSize.toString());
}
@RequestMapping(value = "/file/{fileName:.+}", headers = "!Range", method = RequestMethod.GET)
public void handleRequest(@PathVariable(value = "fileName") String fileName, HttpServletRequest request, HttpServletResponse response) throws Exception {
File file = fileRepository.getFileByName(fileName)
response.addHeader("Accept-Ranges", "bytes");
response.addDateHeader("Last-Modified", file.lastModified());
Long fileSize = file.length();
response.addHeader(HttpHeaderConstants.CONTENT_LENGTH, fileSize.toString());
// Stream file to end user client.
fileDownloadHandler.handle(request, response, file);
}
【问题讨论】:
-
您可以将
HttpServletResponse response作为参数添加到您的方法中,并使用@GetMapping进行注释并执行response.setHeader("Content-Length", "12345");之类的操作 -
@ImpulseTheFox 这就是我们想要做的。我添加了一个代码,用于在 Spring 4.3 的更改之前工作。根本不再调用
handleHeadRequest方法。 :( -
您的问题是如何制作下载服务控制器?
-
@Byeon0gam,不,不是真的。我在问如何让 Spring 调用上面的
handleHeadRequest方法而不是 HTTP HEAD 方法请求的handleRequest方法。 -
@hooknc,你查看我的帖子了吗?
标签: java spring spring-mvc