繁体   English   中英

如何在gzip标头后正确设置spark java中的内容长度

[英]How to correctly set content-length in spark java after gzip header

我正在使用Spark来提供不同类型的内容。 “内容长度”计算正确,但我在使用时遇到问题:

response.header("Content-Encoding", "gzip")

根据他们的文档,当设置该标头时,spark 会自动对内容进行 gzip 压缩……并且它确实做到了。

但是,我之前计算的“内容长度”不再有效,因此我在浏览器中收到“net::ERR_CONTENT_LENGTH_MISMATCH”错误。

自己压缩它,并计算结果大小是不可能的,因为 spark 会再次压缩输出。

我怎么知道火花压缩输出后的结果大小?

更多细节:

我在 Spark 上创建了一个库,它会自动设置这样的标题,有趣的部分看起来像(简化):

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”标头,所以我试图添加它。 在那之前计算是正确的(没有压缩),但是由于 Spark 将压缩输出(因为它检测到“gzip”作为编码),我没有正确设置它的可靠方法。

我能想到的解决这个问题的方法是:

  1. 等到Spark 自动添加该标头(或滚动我自己的分支)。
  2. 在 Spark 压缩输出后找到一种方法来获得该大小。
  3. 以与 Spark 相同的方式压缩它,以便我可以计算大小(但很难看,因为它会将输出压缩两次 == CPU 浪费)。

我当前的解决方案是在使用gzip标头时不设置Content-Length标头(但它不适合大文件,因为浏览器不知道已经下载了多少百分比)。

我希望这些细节能让情况更加明朗。

谢谢澄清!

  1. 是的,现在您正在手动添加它,这就是我要做的并保持这种方式,除非您真的需要Content-Length用于您的用例。 不知道大小有点烦人,但并不少见。
  2. 我很确定使用当前 spark 的内部 API 很难做到这一点。 我昨天玩了它,用 apache commons CountingOutputStream拦截 OutputStreams 并且没有 API 可以在不更改代码的情况下做到这一点,并且它也存在其他问题。 问题还在于,在 spark 压缩输出之后,很可能它已经被刷新并发送回客户端,但是这个标头必须在数据之前发送。 在发送数据之前,您基本上必须知道这一点,因此这是最难的方法。
  3. 是的,最容易实现火花的方法可能是将已经准备好的压缩数据作为ByteArray提供给他(似乎您正在使用 kotlin)并禁用自动压缩。 ByteArrayOutputStream是不错的选择。 这样它至少只被压缩一次。 还有关于设置Content-Encoding标头同时强制 spark 不编码的事情,但这很容易修补。 关于这一点的丑陋之处在于,您必须将整个数据存储在内存中 + 服务器在这一切都被预先计算之前不会开始发送数据,因此用户单击下载和下载开始之间会有延迟。
  4. 如果您的大文件将被多次使用,您可以提前或在第一次运行时预先计算它们的 gzip 大小并缓存该信息。 这样您就可以将数据直接发送到流中,并且您一开始就知道信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM