第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何上傳 gzip 壓縮文件而不將所有內(nèi)容讀入內(nèi)存

如何上傳 gzip 壓縮文件而不將所有內(nèi)容讀入內(nèi)存

Go
慕森卡 2023-08-07 19:01:15
我想知道是否有人可以指出如何進一步優(yōu)化?我不喜歡這樣的事實:我必須將整個文件讀入內(nèi)存并創(chuàng)建文件長度的字節(jié)切片。這是代碼:func newfileUploadRequestWithGzip(uri string, paramName, path string) (*http.Request, error) {    f, err := os.Open(path)    if err != nil {        return nil, err    }    fi, err := f.Stat()    if err != nil {        return nil, err    }    defer f.Close()    body := new(bytes.Buffer)    writer := multipart.NewWriter(body)    part, err := writer.CreateFormFile(paramName, fi.Name())    if err != nil {        return nil, err    }    filebuffer := make([]byte, fi.Size())    var gzbuffer bytes.Buffer    gw, err := gzip.NewWriterLevel(&gzbuffer, gzip.DefaultCompression)    buffer := bufio.NewReader(f)    if _, err = buffer.Read(filebuffer); err != nil {        fmt.Printf("Error in reading file with error: %v\n", err)    }    n, err := gw.Write(filebuffer)    gw.Close()    fmt.Printf("%d:%d => %.2f%%\n", n, len(gzbuffer.Bytes()), float32(len(gzbuffer.Bytes()))/float32(n)*100.0)    io.Copy(part, &gzbuffer)    if writer.Close() != nil {        return nil, err    }    request, requestErr := http.NewRequest("POST", uri, body)    request.Header.Add("Content-Type", writer.FormDataContentType())    return request, requestErr}
查看完整描述

1 回答

?
慕妹3242003

TA貢獻1824條經(jīng)驗 獲得超6個贊

我認為沒有辦法在不將文件讀入內(nèi)存的情況下發(fā)送文件;但是,無需立即將其所有內(nèi)容讀入內(nèi)存即可完成。


如果您不想立即將所有內(nèi)容讀入內(nèi)存,那就不要這樣做 - 并擺脫bytes.Buffer. 和gzip.NewWriter都multipart.Writer.CreateFormFile可以很好地與io.Writer界面配合使用,而不僅僅是bytes.Buffer. http.NewRequest,另一方面,需要一個io.Reader. 雖然bytes.Buffer這似乎是實現(xiàn)這兩者的最佳選擇,但它并不是唯一的選擇。io包提供了一個io.Pipe()創(chuàng)建高效的內(nèi)存管道,這正是我們這里所需要的。


例如,


func newfileUploadRequestWithGzip(uri string, paramName, path string) (*http.Request, error) {

    f, err := os.Open(path)

    if err != nil {

        return nil, err

    }


    fi, err := f.Stat()

    if err != nil {

        f.Close()

        return nil, err

    }


    buf := bufio.NewReader(f)

    r, w := io.Pipe()


    multi := multipart.NewWriter(w)

    part, err := multi.CreateFormFile(paramName, fi.Name())

    if err != nil {

        f.Close()

        return nil, err

    }

    writer, err := gzip.NewWriterLevel(part, gzip.DefaultCompression)

    if err != nil {

        f.Close()

        return nil, err

    }


    go func() {

        _,err := io.Copy(writer, buf)

        w.Close()

        multi.Close()

        writer.Close()

        f.Close()

        if err != nil {

            panic(err) // panic is not good, but how to make it good depends.

        }

    }()


    request, requestErr := http.NewRequest("POST", uri, r)

    request.Header.Add("Content-Type", multi.FormDataContentType())

    return request, requestErr

}

這段代碼非常臭,需要一些工作來重構(gòu)。您的函數(shù)簽名以及函數(shù)的范圍(其職責(zé))或您希望函數(shù)執(zhí)行的操作需要更改,以實現(xiàn)更好的錯誤處理和資源管理。建議拆分功能 - 一個用于準備io.Writers和io.Pipe(),一個用于多部分處理,一個用于請求部分;將整個事物包裝成一個類型并創(chuàng)建私有輔助方法,同時設(shè)置錯誤并使用一種Err() error方法來收集錯誤。但如果不了解用例,就很難做出決定并使其付諸實踐——而且主要是基于意見。


@mh-cbon 這里提供了一個更好看的代碼:https ://play.golang.org/p/i5bocA6-Q4M


查看完整回答
反對 回復(fù) 2023-08-07
  • 1 回答
  • 0 關(guān)注
  • 166 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號