1 回答
TA贡献1824条经验 获得超6个赞
我认为没有办法在不将文件读入内存的情况下发送文件;但是,无需立即将其所有内容读入内存即可完成。
如果您不想立即将所有内容读入内存,那就不要这样做 - 并摆脱bytes.Buffer. 和gzip.NewWriter都multipart.Writer.CreateFormFile可以很好地与io.Writer界面配合使用,而不仅仅是bytes.Buffer. http.NewRequest,另一方面,需要一个io.Reader. 虽然bytes.Buffer这似乎是实现这两者的最佳选择,但它并不是唯一的选择。io包提供了一个io.Pipe()创建高效的内存管道,这正是我们这里所需要的。
例如,
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
}
这段代码非常臭,需要一些工作来重构。您的函数签名以及函数的范围(其职责)或您希望函数执行的操作需要更改,以实现更好的错误处理和资源管理。建议拆分功能 - 一个用于准备io.Writers和io.Pipe(),一个用于多部分处理,一个用于请求部分;将整个事物包装成一个类型并创建私有辅助方法,同时设置错误并使用一种Err() error方法来收集错误。但如果不了解用例,就很难做出决定并使其付诸实践——而且主要是基于意见。
@mh-cbon 这里提供了一个更好看的代码:https ://play.golang.org/p/i5bocA6-Q4M
- 1 回答
- 0 关注
- 127 浏览
添加回答
举报