【问题标题】:Determine Length Of Golang Gzip File Without Reading It?无需阅读即可确定 Golang Gzip 文件的长度?
【发布时间】:2021-03-20 19:52:41
【问题描述】:

我在磁盘上有 gzip 文件,我希望将这些文件以未压缩的形式传输到 HTTP 客户端。为此,我需要发送一个长度标头,然后将未压缩的文件流式传输到客户端。我知道 gzip 协议存储未压缩数据的原始长度,但据我所知,golang 的“compress/gzip”包似乎没有办法获取这个长度。我已经将文件读入一个变量,然后从中获取字符串长度,但这非常低效且浪费内存,尤其是在较大的文件上。

下面我已经发布了我最终使用的代码:

DownloadHandler(w http.ResponseWriter, r *http.Request) {
path := "/path/to/thefile.gz";
openfile, err := os.Open(path);
if err != nil {
    w.WriteHeader(http.StatusNotFound);
    fmt.Fprint(w, "404");
    return;
}

defer openfile.Close();

fz, err := gzip.NewReader(openfile);
if err != nil {
    w.WriteHeader(http.StatusNotFound);
    fmt.Fprint(w, "404");
    return;
}

defer fz.Close()

// Wastefully read data into a string so I can get the length.
s, err := ioutil.ReadAll(fz);
r := strings.NewReader(string(s));

//Send the headers
w.Header().Set("Content-Disposition", "attachment; filename=test");
w.Header().Set("Content-Length", strconv.Itoa(len(s))); // Send length to client.
w.Header().Set("Content-Type", "text/csv");

io.Copy(w, r) //'Copy' the file to the client
}

我希望能够做的是这样的事情:

DownloadHandler(w http.ResponseWriter, r *http.Request) {
path := "/path/to/thefile.gz";
openfile, err := os.Open(path);
if err != nil {
    w.WriteHeader(http.StatusNotFound);
    fmt.Fprint(w, "404");
    return;
}

defer openfile.Close();

fz, err := gzip.NewReader(openfile);
if err != nil {
    w.WriteHeader(http.StatusNotFound);
    fmt.Fprint(w, "404");
    return;
}

defer fz.Close()

//Send the headers
w.Header().Set("Content-Disposition", "attachment; filename=test");
w.Header().Set("Content-Length", strconv.Itoa(fz.Length())); // Send length to client.
w.Header().Set("Content-Type", "text/csv");

io.Copy(w, fz) //'Copy' the file to the client
}

有人知道如何在 golang 中获取 gzip 压缩文件的未压缩长度吗?

【问题讨论】:

  • 通过解压得到未压缩的长度。为什么不使用分块编码?
  • 为什么不使用Content-Encoding: gzip并发送压缩文件(以及Content-Length标头中压缩文件的长度)?
  • @ErwinBolwidt - 这不需要客户特别允许还是所有客户都支持?
  • 取决于客户。浏览器已经支持它十年了。 webmasters.stackexchange.com/questions/22217/…
  • 客户端会以它所支持的响应。

标签: go gzip


【解决方案1】:

gzip 格式可能会提供未压缩的长度,但实际上并没有。不幸的是,获得未压缩长度的唯一可靠方法是解压缩 gzip 流。 (您可以只计算字节数,而不是将未压缩的数据保存在任何地方。)

请参阅this answer 了解原因。

【讨论】:

  • 好吧,至少这是一个答案,不是想要的答案,而是一个答案。
  • 没有。我认为你将不得不做你浪费的事情。这只是浪费内存。如果内存有问题,例如这些真的很大,那么你可以通过读取 gzip 文件两次来浪费 CPU。一次统计字节数,第二次发送出去。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多