确定Golang Gzip文件的长度而不读取它?

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


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


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压缩文件的未压缩长度?


红颜莎娜
浏览 131回答 1
1回答

繁花不似锦

gzip 格式可能看起来提供了未压缩的长度,但实际上它并没有。不幸的是,获得未压缩长度的唯一可靠方法是解压缩gzip流。(您可以只计算字节数,而不将未压缩的数据保存在任何地方。请参阅此答案以了解原因。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go