1 回答

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
- 1 回答
- 0 關(guān)注
- 166 瀏覽
添加回答
舉報