通过HTTPS下载JSF不起作用,即使在HTTP下也可以正常工作



我正在处理一个奇怪的错误,这个错误只有在生产中通过https连接才能重现。首先,我试图下载一个*.cvs文件,我的backingbean代码如下所示:

ExternalContext externalContext = facesContext.getExternalContext();
try (OutputStream outputStream = externalContext.getResponseOutputStream()) {
String exportFileName = exportHandler.getExportFileName();
String contentType = externalContext.getMimeType(exportFileName);
externalContext.responseReset();
externalContext.setResponseCharacterEncoding(CHARSET);
externalContext.setResponseContentType(contentType);
externalContext.setResponseHeader("Content-disposition", "attachment; filename="" + exportFileName + """);
int length = exportHandler.writeCsvTo(outputStream); // with a BufferedWriter the lines are written and the bytes are summed up.
externalContext.setResponseContentLength(length);
outputStream.flush();
}
facesContext.responseComplete();

通过http连接或本地主机(甚至本地主机上的https也可以(,一切都很好,但在通过https连接的生产中,不同的web浏览器会给出不同的错误消息。Chrome显示以下消息:"位于…的网页可能暂时关闭,或者可能已永久移动到新的网址。ERR_HTTP2_PROTOCOL_ERROR"在Firefox下开始加载,然后什么都没发生,因为这需要很长时间。在IE下:"与网站的连接已重置。错误代码:INET_E_DOWNLOAD_FAILURE">

我的看法是,这与响应内容的长度有关,因为我不确定在编写Outputstream后是否还需要它。响应标头如下所示:

  • 连接:保持活动
  • 内容处置:附件;filename="test.csv">
  • 内容类型:text.csv;字符集=ISO-8859-15
  • 日期:2020年5月4日星期一10:16:41 GMT
  • 传输编码:分块

不知道为什么我的响应会以分块传输编码结束,据我所知,只有在未设置内容长度时才会发生这种情况。有人知道吗,我在响应中是否遗漏了一些头部约束,比如设置缓存控制?

区别实际上可能是HTTP1.1和2.0之间的区别,而不是直接的https和http。之所以会出现这种情况,可能是因为https允许在握手期间将协议升级到2.0,而在基本http中则不会进行此类协商。

考虑到这一点,浏览器中的头解析实现可能会有所不同。如果非要我猜测的话,这是关于内容处置文件名的问题。

在HTTP2中,如果内容处置文件名包含非US-ASCII字符,大多数浏览器将无法解析该文件名。HTTP1.1的实现对此更加宽容。

您仍然可以使用具有内容处置filename*属性的utf-8文件名。

目前最受支持的内容处置格式是:

attachment; filename="<us-ascii filename>"; filename*=utf-8''<url-encoded-utf-8-filename>

即。

attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates

相关内容

最新更新