是否可以计算文件的md5并将文件同时写入磁盘?

时间:2019-09-09 09:06:27

标签: go

我用Go编写了一个文件上传器。将文件的md5保存到磁盘时,我希望将其作为文件名。

解决此问题的最佳方法是什么?

我这样保存文件:

reader, _ := r.MultipartReader()
p, _ := reader.NextPart()

f, _ := os.Create("./filename") // here I need md5 as a file name
defer f.Close()

lmt := io.LimitReader(p, maxSize + 1)
written, _ := io.Copy(f, lmt)
if written > maxSize {
    os.Remove(f.Name())
}

3 个答案:

答案 0 :(得分:4)

这是一个使用io.TeeReader同时执行计算和复制的示例

https://play.golang.org/p/IJJQiaeTOBh

package main

import (
    "crypto/sha256"
    "fmt"
    "io"
    "os"
    "strings"
)

func main() {

    var s io.Reader = strings.NewReader("some data")

    // maxSize := 4096
    // s = io.LimitReader(s, maxSize + 1)

    h := sha256.New()
    tr := io.TeeReader(s, h)
    io.Copy(os.Stdout, tr)
    fmt.Printf("\n%x", h.Sum(nil))

}
// Output:
//some data
//1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee

和比较测试的正确性

$ echo -n "some data" | sha256sum -
1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee  -

答案 1 :(得分:1)

我使用AT+FCLASS=8来创建2个缓冲区(而不是使用io.TeeReader)(我将使用第一个缓冲区来计算md5,第二个缓冲区来写入具有md5名称的文件)

io.MultiWriter

答案 2 :(得分:0)

我喜欢 TeeReader here 的解决方案,但将其简化如下:

type HashReader struct {
    io.Reader
    hash.Hash
}

func NewHashReader(r io.Reader, h hash.Hash) HashReader {
    return HashReader{io.TeeReader(r, h), h}
}

func NewMD5Reader(r io.Reader) HashReader {
    return NewHashReader(r, md5.New())
}

func main() {
    dataReader := bytes.NewBufferString("Hello, world!")
    hashReader := NewMD5Reader(dataReader)

    resultBytes := make([]byte, dataReader.Len())
    _, err := hashReader.Read(resultBytes)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(hex.EncodeToString(hashReader.Sum(nil)))
}

md5 的十六进制编码字符串对我来说看起来更熟悉,但可以随意编码 hashReader.Sum(nil) 的结果字节数组。

附言关于操场示例的另一件事。他们在 EOF 上分配 md5 结果,但绝对不是所有消费者都在 EOF 之前阅读。由于 Hash 对象存储了当前的哈希计算,因此消费完成后调用 hashReader.Sum 并使用结果就足够了。