Golang io.copy在请求正文中两次

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

流工作正常,但我想从请求正文中进行sha1哈希处理。我需要io。复制身体两次。创建了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.Copy上执行哈希处理的包装器

// this works for either a reader or writer, 

// but if you use both in the same time the hash will be wrong.

type Hasher struct {

io.Writer

io.Reader

hash.Hash

Size uint64

}

func (h *Hasher) Write(p []byte) (n int, err error) {

n, err = h.Writer.Write(p)

h.Hash.Write(p)

h.Size += uint64(n)

return

}

func (h *Hasher) Read(p []byte) (n int, err error) {

n, err = h.Reader.Read(p)

h.Hash.Write(p[:n]) //on error n is gonna be 0 so this is still safe.

return

}

func (h *Hasher) Sum() string {

return hex.EncodeToString(h.Hash.Sum(nil))

}

func (h *UploadHandle) Read() (io.Reader, string, int64, error) {

var b bytes.Buffer

hashedReader := &Hasher{Reader: h.Contents, Hash: sha1.New()}

n, err := io.Copy(&b, hashedReader)

if err != nil {

return nil, "", 0, err

}

return &b, hashedReader.Sum(), n, nil

}

//由于我完全忘记了io.TeeReader存在,因此根据@Dustin的评论更新了版本。

func (h *UploadHandle) Read() (io.Reader, string, int64, error) {

var b bytes.Buffer

hash := sha1.New()

n, err := io.Copy(&b, io.TeeReader(h.Contents, hash))

if err != nil {

return nil, "", 0, err

}

return &b, hex.EncodeToString(hash.Sum(nil)), n, nil

}

以上是 Golang io.copy在请求正文中两次 的全部内容, 来源链接: utcz.com/qa/418126.html

回到顶部