Golang将多个文件添加到HTTP多部分请求中

huangapple go评论81阅读模式
英文:

Golang adding multiple files to a http multipart request

问题

目前我正在分别处理两个多部分请求。

  1. 包含文件的 blob
  2. 包含 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.

  1. Contains the file as a blob
  2. 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(&quot;Failed to peek the body size %v&quot;, err)
}
if bodySize &gt; constants.MaxDropSize {
return nil, errors.New(&quot;The size of the body is to big&quot;)
}
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 &lt;- err
return
}
_, err = io.Copy(part, bodyReader)
if err == nil {
err = writer.Close()
}
errChan &lt;- err
}()
uploadUrl := fmt.Sprintf(&quot;%s/drops/upload&quot;, c.Server)
req, err := http.NewRequest(&quot;POST&quot;, uploadUrl, pipeReader)
if err != nil {
return nil, err
}
req.Header.Add(&quot;Content-Type&quot;, writer.FormDataContentType())
req.Body = ioutil.NopCloser(pipeReader)
resp, err := c.Do(req)
if err != nil {
return nil, fmt.Errorf(&quot;Failed doing request: %v&quot;, err)
}
defer resp.Body.Close()
// Handling the error the routine may caused
if err := &lt;-errChan; err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf(&quot;The server responded with a status %d&quot;, resp.StatusCode)
}
return &amp;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(&quot;meta&quot;, h.DropRef + &quot;.json&quot;)
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.

huangapple
  • 本文由 发表于 2014年9月10日 14:09:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/25758417.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定