Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Go和云存储从文件读取器计算CRC32校验和_Go_Google Cloud Functions_Google Cloud Storage - Fatal编程技术网

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

使用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

我正在通过一个用Go编写的Api将文件上传到GCP云存储,它工作正常(选项I)。我想知道我是否可以在不将文件存储在内存中的情况下计算校验和。我尝试了选项II中的代码,在读卡器中循环并更新校验和,但没有成功。似乎我必须在进行第一次写入之前初始化校验和值CRC32C,如文档在“ObjectAttrs”中所述:

我猜我不能同时流式传输和生成CRC32校验和。是这样吗?。云存储Go客户端在writer?中默认没有任何校验和机制吗

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

备选案文一:

...

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不匹配。