【问题标题】:Spring MVC : Return CSSSpring MVC:返回 CSS
【发布时间】:2014-02-07 16:47:21
【问题描述】:

我的目标是合并/缩小所有 css 文件并将结果作为字符串返回。

这是我的 Spring 测试方法:

@RequestMapping(value = "/stylesheet.css", method = RequestMethod.GET, produces = "text/css")
@ResponseBody
public void css(HttpServletResponse response) {
    File path = new File(servletContext.getRealPath("/WEB-INF/includes/css/"));

    File[] files = path.listFiles(...);

    for (File file : files) {
        InputStream is = new FileInputStream(file);
        IOUtils.copy(is, response.getOutputStream());
        response.flushBuffer();

        is.close();
    }
}

这适用于 Chrome、Firefox 和 Safari,但不适用于 IE 和 Opera。

在检查器中进行一些检查后,URL https://host/project/stylesheet.css 正在加载到每个浏览器中。我可以看到内容,但似乎无法识别为text/css

此外,即使使用produces = "text/css",我也无法在所有浏览器中看到content-type http 标头。

IE登录错误:

CSS ignored because of mime type incompatibility

有谁知道如何正确地做到这一点?

工作代码:

@RequestMapping(value = "/stylesheet.css", method = RequestMethod.GET)
public ResponseEntity<Void> css(HttpServletResponse response) {
    response.setContentType("text/css");

    File path = new File(servletContext.getRealPath("/WEB-INF/includes/css/"));

    File[] files = path.listFiles(...);

    for (File file : files) {
        InputStream is = new FileInputStream(file);
        IOUtils.copy(is, response.getOutputStream());
        IOUtils.closeQuietly(is);
    }

    response.flushBuffer();

    return new ResponseEntity<Void>(HttpStatus.OK);
}

【问题讨论】:

  • 查看stackoverflow.com/questions/8226863/… 但我注意到您的控制器正在生成text/css。 IE 的精确版本可能很重要。
  • 感谢您的回答。我实际上使用的是 IE11。
  • 您正在使用哪些消息转换器(您的 bean 配置文件的 &lt;mvc:message-converters&gt; 部分中有什么)?这可能是一个内容协商问题,结果使用了错误的 MIME 类型。
  • 你能检查生成响应的标题吗?它应该包含: Content-Type: text/css
  • 我不想返回字符串...流更适合内存使用。

标签: java css spring spring-mvc


【解决方案1】:

我怀疑问题是由于您使用了HttpServletResponse.flushBuffer()

正如HttpServletRequest 的 API 所述:

强制将缓冲区中的任何内容写入客户端。一个电话 对此方法自动提交响应,即状态 将编写代码和标题。

我的假设是,在控制器上的方法返回后,Spring 会尝试在 HttpServletResponse 上设置 Content-Type 标头。但是,由于您已通过调用 HttpServletResponse.flushBuffer() 提交了响应,因此它无法执行此操作。

我会尝试:

  • 将 HttpServletResponse 注入您的控制器并在代码中自己设置标头调用HttpServletResponse.flushBuffer()
  • 删除您对HttpServletRequest.flushBuffer() 的使用

【讨论】:

  • 感谢您的回答!我已经尝试过 response.setContentType("text/css");setHeader(...) 甚至内容长度,但它不起作用:(。删除 flushBuffer 也不起作用。
  • 实际上,我在任何写入之前添加了setContentType,它确实有效!谢谢!
  • 这解决了我的相关问题——虽然我没有使用 flushBuffer(),但我使用的是 getInputStream() 和 IOUtils.copy(inputStream, response.getOutputStream())。这些方法的运行方式阻止了 response.setContentType 的发生。将 response.setContentType 移到这些代码行之上解决了我的问题。谢谢!
【解决方案2】:

由于您将内容直接写入输出流,因此无需使用@ResponseBody。您只需要确保设置了Content-Type 响应标头。此外,最好返回 ResponseEntity(而不是 void)以向 Spring 表明您正在自己处理响应。

@RequestMapping(value = "/stylesheet.css", method = RequestMethod.GET)
public ResponseEntity css(HttpServletResponse response) {

    // Set the content-type
    response.setHeader("Content-Type", "text/css");

    File path = new File(servletContext.getRealPath("/WEB-INF/includes/css/"));

    File[] files = path.listFiles(...);

    for (File file : files) {
        InputStream is = new FileInputStream(file);
        IOUtils.copy(is, response.getOutputStream());
        IOUtils.closeQuietly(is);
    }

    response.flushBuffer();

    return new ResponseEntity(HttpStatus.OK)
}

【讨论】:

  • 首先,感谢您的回答! Rob Blake 之前得到了答案,所以我接受了他的回答,抱歉。但是,感谢您的有用提示!我使用@ResponseBody 仅用于测试(当我编写第一个方法时它不存在)。我已经理解了这个问题:我们需要在正确处理任何写入/刷新之前指定Content-Type。另外,感谢closeQuietlyResponseEntity 的提示。
猜你喜欢
  • 2019-10-22
  • 1970-01-01
  • 2018-03-17
  • 2016-11-23
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 2013-06-11
相关资源
最近更新 更多