如何在 gzip header 之后在 spark java 中正确设置 content-length
How to correctly set content-length in spark java after gzip header
我正在使用 Spark 来提供不同类型的内容。 “Content-Length”计算正确,但我在使用时遇到问题:
response.header("Content-Encoding", "gzip")
根据 their documentation,当设置 header 时,spark 会自动对内容进行 gzip 压缩...它确实做到了。
但是,我之前计算的“Content-Length”不再有效,因此我在浏览器中收到 'net::ERR_CONTENT_LENGTH_MISMATCH' 错误。
自己对其进行 Gzip 压缩,并且无法计算结果大小,因为 spark 会再次压缩输出。
我如何知道 spark 压缩输出后的结果大小是多少?
更多详情:
我在 Spark 上创建了一个库,它自动设置了这样的 headers,有趣的部分看起来像(简化):
if(request.headers("Accept-Encoding")?.contains("gzip")) {
response.header("Content-Encoding", "gzip")
// How to get or calculate the resulting size?
response.header("Content-Length", ???????)
}
问题是 Spark 没有自动设置“Content-Length”header,所以我正在尝试添加它。直到那时计算都是正确的(没有压缩),但是由于 Spark 将压缩输出(因为它检测到“gzip”作为编码),我没有可靠的方法来正确设置它。
我能想到的解决这个问题的方法是:
- 等到 Spark adds that header automatically(或滚动我自己的分支)。
- 找到一种在 Spark 压缩输出后获得该大小的方法。
- 以与 Spark 相同的方式压缩它,这样我就可以计算大小(但很难看,因为它会将输出压缩两次 == CPU 浪费)。
我目前的解决方案是在使用 gzip
header 时不设置 Content-Length
header (但对于 large-size 文件作为浏览器来说并不理想不知道已经下载了多少百分比)。
我希望这些细节能使情况更加明朗。
感谢您的澄清!
- 是的,现在您手动添加它,这就是我要做的并保持这种方式,除非您确实需要
Content-Length
用于您的用例。不知道大小有点烦人,但并不少见。
- 我很确定使用当前 spark 的内部 API 很难做到这一点。我昨天玩过它,用 apache commons
CountingOutputStream
拦截 OutputStreams 并且没有 API 在不更改代码的情况下做到这一点并且它还有其他问题。问题还在于,在 spark 压缩输出之后,它很可能已经被发送刷新并发送回客户端,但是这个 header 必须在数据之前发送。在发送数据之前你基本上必须知道这一点,所以这是最难的方法。
- 是的,最容易实现 spark 的方法可能是为他提供已经准备好的压缩数据作为
ByteArray
(好像您正在使用 kotlin)并禁用 auto-compression。 ByteArrayOutputStream
是个好方法。这样它至少只被压缩一次。还有关于设置 Content-Encoding
header 的事情,同时强制 spark 不编码,但这是简单的补丁。丑陋的是,你必须将整个数据存储在内存中+服务器不会在这一切都是 pre-calculated 之前开始发送数据,所以用户点击下载和下载开始之间会有延迟。
- 如果您的大文件将被多次使用,您可以 pre-calculate 提前或先 运行 压缩它们的大小并缓存该信息。这样您就可以将数据直接发送到流中,并且在开始时就知道信息。
我正在使用 Spark 来提供不同类型的内容。 “Content-Length”计算正确,但我在使用时遇到问题:
response.header("Content-Encoding", "gzip")
根据 their documentation,当设置 header 时,spark 会自动对内容进行 gzip 压缩...它确实做到了。
但是,我之前计算的“Content-Length”不再有效,因此我在浏览器中收到 'net::ERR_CONTENT_LENGTH_MISMATCH' 错误。
自己对其进行 Gzip 压缩,并且无法计算结果大小,因为 spark 会再次压缩输出。
我如何知道 spark 压缩输出后的结果大小是多少?
更多详情:
我在 Spark 上创建了一个库,它自动设置了这样的 headers,有趣的部分看起来像(简化):
if(request.headers("Accept-Encoding")?.contains("gzip")) {
response.header("Content-Encoding", "gzip")
// How to get or calculate the resulting size?
response.header("Content-Length", ???????)
}
问题是 Spark 没有自动设置“Content-Length”header,所以我正在尝试添加它。直到那时计算都是正确的(没有压缩),但是由于 Spark 将压缩输出(因为它检测到“gzip”作为编码),我没有可靠的方法来正确设置它。
我能想到的解决这个问题的方法是:
- 等到 Spark adds that header automatically(或滚动我自己的分支)。
- 找到一种在 Spark 压缩输出后获得该大小的方法。
- 以与 Spark 相同的方式压缩它,这样我就可以计算大小(但很难看,因为它会将输出压缩两次 == CPU 浪费)。
我目前的解决方案是在使用 gzip
header 时不设置 Content-Length
header (但对于 large-size 文件作为浏览器来说并不理想不知道已经下载了多少百分比)。
我希望这些细节能使情况更加明朗。
感谢您的澄清!
- 是的,现在您手动添加它,这就是我要做的并保持这种方式,除非您确实需要
Content-Length
用于您的用例。不知道大小有点烦人,但并不少见。 - 我很确定使用当前 spark 的内部 API 很难做到这一点。我昨天玩过它,用 apache commons
CountingOutputStream
拦截 OutputStreams 并且没有 API 在不更改代码的情况下做到这一点并且它还有其他问题。问题还在于,在 spark 压缩输出之后,它很可能已经被发送刷新并发送回客户端,但是这个 header 必须在数据之前发送。在发送数据之前你基本上必须知道这一点,所以这是最难的方法。 - 是的,最容易实现 spark 的方法可能是为他提供已经准备好的压缩数据作为
ByteArray
(好像您正在使用 kotlin)并禁用 auto-compression。ByteArrayOutputStream
是个好方法。这样它至少只被压缩一次。还有关于设置Content-Encoding
header 的事情,同时强制 spark 不编码,但这是简单的补丁。丑陋的是,你必须将整个数据存储在内存中+服务器不会在这一切都是 pre-calculated 之前开始发送数据,所以用户点击下载和下载开始之间会有延迟。 - 如果您的大文件将被多次使用,您可以 pre-calculate 提前或先 运行 压缩它们的大小并缓存该信息。这样您就可以将数据直接发送到流中,并且在开始时就知道信息。