使用Go和云存储从文件读取器计算CRC32校验和



我正在通过Go中编写的Api将文件上传到GCP云存储,它运行良好(选项I(。我想知道我是否可以在不将文件存储在内存中的情况下计算校验和。我已经尝试了选项II中的代码,在阅读器中循环并更新校验和,但没有起作用,似乎我必须在进行第一次写入之前预先初始化校验和值CRC32C,正如文档中所说的那样;ObjectAttrs":https://godoc.org/cloud.google.com/go/storage#Writer

我猜我不能同时流式传输和生成CRC32校验和。是这样吗?。Cloud Storage Go客户端在写入程序中默认没有任何校验和机制吗?。

(我跳过了代码示例中的错误(

选项一:

...
func example(w http.ResponseWriter, r *http.Request) {
file, header, err := r.FormFile("file")
defer file.Close()
//create empty buffer
buf := bytes.NewBuffer(nil)
//Writer 
wc := bucket.Object(filename).NewWriter(ctx)
//calculate checksum
wc.CRC32C = crc32.Checksum(buf.Bytes(), crc32.MakeTable(crc32.Castagnoli))
wc.SendCRC32C = true
//copy buffer to bucket
_, err = io.Copy(wc, buf)
wc.Close()
...
}

选项二:

...
func example(w http.ResponseWriter, r *http.Request) {
file, header, err := r.FormFile("file")
defer file.Close()
var err error
table := crc32.MakeTable(crc32.Castagnoli)
wc := bucket.Object(filename).NewWriter(ctx)
checksum := crc32.Checksum([]byte(""), table)
wc.SendCRC32C = true
buf := make([]byte, 32*1024)
for {
nr, er := file.Read(buf)
if nr > 0 {
checksum = crc32.Update(checksum, table, buf[:nr])
nw, ew := wc.Write(buf[:nr])
}
if er != nil {
if er == io.EOF {
wc.CRC32C = checksum
break
}
err = er
break
}
}
wc.Close()
...
}

使用io.Writer包装器,因为大多数哈希器都通过Write方法更新其哈希。使用这种方法,不需要中间缓冲区,更重要的是,它将主逻辑从管理哈希状态变化的任务中解放出来。

因此,使用helper方法,您可以为任何CRC32多项式创建一个自定义哈希器,并将其绑定到任何目标io.Writer:

import (
"hash"
"hash/crc32"
"io"
)
func NewCRCwriter(poly uint32, w io.Writer) *CRCwriter {
return &CRCwriter{
h: crc32.New(crc32.MakeTable(poly)),
w: w,
}
}
type CRCwriter struct {
h hash.Hash32
w io.Writer
}
func (c *CRCwriter) Write(p []byte) (n int, err error) {
n, err = c.w.Write(p)  // with each write ...
c.h.Write(p)           // ... update the hash
return
}
func (c *CRCwriter) Sum() uint32 { return c.h.Sum32() } // final hash

在您的用例中利用这一点:

file, header, err := r.FormFile("file")      // io.Reader
defer file.Close()
wc := bucket.Object(filename).NewWriter(ctx) // io.Writer
crcw := NewCRCwriter(crc32.Castagnoli, wc)   // wrapped io.Writer
_, err = io.Copy(crcw, file) // content will be copied and hashed
if err != nil { /* */ }
wc.CRC32C = crcw.Sum() // final CRC32 hash
wc.SendCRC32C = true 
wc.Close()

相关内容

  • 没有找到相关文章

最新更新