英文:
Computing the Content Length of a Multipart form Post
问题
我正在尝试上传一个文件而不将其加载到内存中,如下所示。像S3这样的服务在这种情况下需要设置Content-Length
。是否有Go语言内置的方法可以实现这一点,还是我需要自己计算它。
package main
import (
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, chan error, error) {
file, err := os.Open(path)
if err != nil {
return nil, nil, err
}
bodyReader, bodyWriter := io.Pipe()
multiWriter := multipart.NewWriter(bodyWriter)
errChan := make(chan error, 1)
go func() {
defer bodyWriter.Close()
defer file.Close()
part, err := multiWriter.CreateFormFile(paramName, filepath.Base(path))
if err != nil {
errChan <- err
return
}
if _, err := io.Copy(part, file); err != nil {
errChan <- err
return
}
for k, v := range params {
if err := multiWriter.WriteField(k, v); err != nil {
errChan <- err
return
}
}
errChan <- multiWriter.Close()
}()
req, err := http.NewRequest("POST", uri, bodyReader)
return req, errChan, err
}
非常感谢您的帮助。
英文:
I'm trying to upload a file without loading it into memory, as shown below. Services like S3 need a Content-Length
set in such cases. Is there a go-lang built-in to do that, or do I have to compute it myself.
package main
import (
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, chan error, error) {
file, err := os.Open(path)
if err != nil {
return nil, nil, err
}
bodyReader, bodyWriter := io.Pipe()
multiWriter := multipart.NewWriter(bodyWriter)
errChan := make(chan error, 1)
go func() {
defer bodyWriter.Close()
defer file.Close()
part, err := multiWriter.CreateFormFile(paramName, filepath.Base(path))
if err != nil {
errChan <- err
return
}
if _, err := io.Copy(part, file); err != nil {
errChan <- err
return
}
for k, v := range params {
if err := multiWriter.WriteField(k, v); err != nil {
errChan <- err
return
}
}
errChan <- multiWriter.Close()
}()
req, err := http.NewRequest("POST", uri, bodyReader)
return req, errChan, err
}
Any help would be much appreciated.
答案1
得分: 5
> 如果存在Body,Content-Length小于等于0且TransferEncoding未设置为"identity",Write会将"Transfer-Encoding: chunked"添加到头部
这意味着如果你没有设置Content-Length
,http.Request.Write
将使用分块传输编码。这个编码被添加到HTTP/1.1
中,以消除像这样的流式传输需要计算Content-Length
的需求。
因此,通常Go程序使用分块编码,不需要设置Content-Length
。任何现代的HTTP堆栈都应该支持分块传输编码。
然而,S3不支持分块传输编码,所以我认为你需要自己计算Content-Length
。
英文:
In the docs for http.Request.Write it states
> If Body is present, Content-Length is <= 0 and TransferEncoding hasn't
> been set to "identity", Write adds "Transfer-Encoding: chunked" to the
> header
Which means if you don't set a Content-Length
, http.Request.Write
will use chunked transfer encoding. This was added to HTTP/1.1
to get rid of the need to calculate the Content-Length
for streaming transfers just like this.
So normally Go programs use chunked encoding and there is no need to set Content-Length
. Any modern HTTP stack should support chunked transfer encoding.
However S3 does not support chunked transfer encoding, so I think you'll have to calculate Content-Length
yourself.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论