io - Golang io.copy 在请求正文上两次

标签 io go multipart

我正在构建一个 blob 存储系统,我选择 Go 作为编程语言。 我创建了一个流来执行从客户端到 Blob 服务器的多部分文件上传。

流工作正常,但我想从请求正文中创建一个 sha1 哈希。我需要 io.Copy body 两次。 sha1 被创建,但之后多部分流 0 个字节。

  1. 用于创建哈希
  2. 用于将正文作为多部分流式传输

知道我该怎么做吗?

客户端上传

func (c *Client) Upload(h *UploadHandle) (*PutResult, error) {
body, bodySize, err := h.Read()
if err != nil {
    return nil, err
}

// Creating a sha1 hash from the bytes of body
dropRef, err := drop.Sha1FromReader(body)
if err != nil {
    return nil, err
}

bodyReader, bodyWriter := io.Pipe()
writer := multipart.NewWriter(bodyWriter)

errChan := make(chan error, 1)
go func() {
    defer bodyWriter.Close()
    part, err := writer.CreateFormFile(dropRef, dropRef)
    if err != nil {
        errChan <- err
        return
    }
    if _, err := io.Copy(part, body); err != nil {
        errChan <- err
        return
    }
    if err = writer.Close(); err != nil {
        errChan <- err
    }
}()

req, err := http.NewRequest("POST", c.Server+"/drops/upload", bodyReader)
req.Header.Add("Content-Type", writer.FormDataContentType())
resp, err := c.Do(req)
if err != nil {
    return nil, err
}
  .....
 }

sha1 函数

func Sha1FromReader(src io.Reader) (string, error) {
hash := sha1.New()
_, err := io.Copy(hash, src)
if err != nil {
    return "", err
}
return hex.EncodeToString(hash.Sum(nil)), nil

}

上传句柄

func (h *UploadHandle) Read() (io.Reader, int64, error) {
var b bytes.Buffer

hw := &Hasher{&b, sha1.New()}
n, err := io.Copy(hw, h.Contents)

if err != nil {
    return nil, 0, err
}

return &b, n, nil

}

最佳答案

我建议使用 io.TeeReader如果您想同时通过 sha1 推送来自 blob 的所有读取。

bodyReader := io.TeeReader(body, hash)

现在由于在上传过程中消耗了 bodyReader,哈希值会自动更新。

关于io - Golang io.copy 在请求正文上两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25671305/

相关文章:

c++ - 在吃 EOF 后重用 std::cin

json - 使用自定义 MarshalJSON() 方法嵌入结构的惯用方法

apache - 无法上传大于 1 MB 的文件

java - 多部分文件上传 Spring Boot

android - Volley 请求失败,如果字符串的长度很长

java - 如何在不知道项目路径的情况下访问项目中的现有目录 Java

java - 使用 RandomAccessFile.writeBytes() 写入的文件中出现意外的额外字符

python - 如何使用 PyCall 在 Julia 中使用内置的 Python read() 函数?

go - Go Web 服务器在哪里查找文件

go - 如何在 Go 中获取 math/big.Float 的指数?