使用Go和云存储从文件读取器计算CRC32校验和
我正在通过一个用Go编写的Api将文件上传到GCP云存储,它工作正常(选项I)。我想知道我是否可以在不将文件存储在内存中的情况下计算校验和。我尝试了选项II中的代码,在读卡器中循环并更新校验和,但没有成功。似乎我必须在进行第一次写入之前初始化校验和值CRC32C,如文档在“ObjectAttrs”中所述: 我猜我不能同时流式传输和生成CRC32校验和。是这样吗?。云存储Go客户端在writer?中默认没有任何校验和机制吗 (我跳过了代码示例中的错误) 备选案文一:使用Go和云存储从文件读取器计算CRC32校验和,go,google-cloud-functions,google-cloud-storage,Go,Google Cloud Functions,Google Cloud Storage,我正在通过一个用Go编写的Api将文件上传到GCP云存储,它工作正常(选项I)。我想知道我是否可以在不将文件存储在内存中的情况下计算校验和。我尝试了选项II中的代码,在读卡器中循环并更新校验和,但没有成功。似乎我必须在进行第一次写入之前初始化校验和值CRC32C,如文档在“ObjectAttrs”中所述: 我猜我不能同时流式传输和生成CRC32校验和。是这样吗?。云存储Go客户端在writer?中默认没有任何校验和机制吗 (我跳过了代码示例中的错误) 备选案文一: ... func examp
...
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()
@colm.anseo似乎不起作用,您建议的解决方案是上传文件,但我认为没有检查校验和。例如,如果将随机数指定给w.CRC32C。它也会起作用。然后,如果将wc.SendCRC32C=true移到io.Copy之前,您将意识到云存储会抱怨这与计算的CRC32C不匹配。