英文:
Golang adding multiple files to a http multipart request
问题
目前我正在分别处理两个多部分请求。
- 包含文件的 blob
- 包含 blob 描述的 json 文件
如何使用多部分同时上传它们?
这是运行两次的请求。我想在这个请求中添加这两个文件。
func(c *Client) Upload(h *UploadHandle) (*PutResult, error) {
bodyReader, bodySize, err := h.Read()
if err != nil {
return nil, fmt.Errorf("Failed to peek the body size %v", err)
}
if bodySize > constants.MaxDropSize {
return nil, errors.New("The size of the body is too big")
}
pipeReader, pipeWriter := io.Pipe()
writer := multipart.NewWriter(pipeWriter)
errChan := make(chan error, 1)
go func() {
defer pipeWriter.Close()
part, err := writer.CreateFormFile(h.DropRef, h.DropRef)
if err != nil {
errChan <- err
return
}
_, err = io.Copy(part, bodyReader)
if err == nil {
err = writer.Close()
}
errChan <- err
}()
uploadUrl := fmt.Sprintf("%s/drops/upload", c.Server)
req, err := http.NewRequest("POST", uploadUrl, pipeReader)
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", writer.FormDataContentType())
req.Body = ioutil.NopCloser(pipeReader)
resp, err := c.Do(req)
if err != nil {
return nil, fmt.Errorf("Failed doing request: %v", err)
}
defer resp.Body.Close()
// 处理例程可能引起的错误
if err := <-errChan; err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("The server responded with a status %d", resp.StatusCode)
}
return &PutResult{h.DropRef, bodySize}, nil
}
希望这可以帮助到你!
英文:
Currently i am streaming 2 multipart requests separately.
- Contains the file as a blob
- contains a json file as a description of the blob
How can i upload them at the same time with multipart?
this is the request that runs 2 times. I want to add the 2 files in this 1 request
func(c *Client) Upload(h *UploadHandle) (*PutResult, error) {
bodyReader, bodySize, err := h.Read()
if err != nil {
return nil, fmt.Errorf("Failed to peek the body size %v", err)
}
if bodySize > constants.MaxDropSize {
return nil, errors.New("The size of the body is to big")
}
pipeReader, pipeWriter := io.Pipe()
writer := multipart.NewWriter(pipeWriter)
errChan := make(chan error, 1)
go func() {
defer pipeWriter.Close()
part, err := writer.CreateFormFile(h.DropRef, h.DropRef)
if err != nil {
errChan <- err
return
}
_, err = io.Copy(part, bodyReader)
if err == nil {
err = writer.Close()
}
errChan <- err
}()
uploadUrl := fmt.Sprintf("%s/drops/upload", c.Server)
req, err := http.NewRequest("POST", uploadUrl, pipeReader)
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", writer.FormDataContentType())
req.Body = ioutil.NopCloser(pipeReader)
resp, err := c.Do(req)
if err != nil {
return nil, fmt.Errorf("Failed doing request: %v", err)
}
defer resp.Body.Close()
// Handling the error the routine may caused
if err := <-errChan; err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("The server responded with a status %d", resp.StatusCode)
}
return &PutResult{h.DropRef, bodySize}, nil
}
答案1
得分: 5
你只需要再次调用CreateFormFile
(或CreateFormField
),并将你的 JSON 写入返回的 writer 中。
j, err := writer.CreateFormFile("meta", h.DropRef + ".json")
enc := json.NewEncoder(j)
enc.Encode(some-struct-you-want-to-write-as-json)
只需确保在创建新文件之前完成写入第一个文件,因为根据文档:
调用 CreatePart 后,之前的任何部分都不能再写入。
英文:
You simply call CreateFormFile
again (or CreateFormField
) and write your json to the writer returned.
j, err := writer.CreateFormFile("meta", h.DropRef + ".json")
enc := json.NewEncoder(j)
enc.Encode(some-struct-you-want-to-write-as-json)
Just make sure you finish writing your first file before creating a new one, because according to the docs:
> After calling CreatePart, any previous part may no longer be written to.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论