在Go中计算MultipartForm文件上传的SHA1哈希值

时间:2014-07-16 18:29:06

标签: file-upload web go

我试图计算上传文件的sha1哈希值,但到目前为止,我还处于死胡同。示例代码如下:

err := req.ParseMultipartForm(200000)
if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
}

m := req.MultipartForm
files := m.File["Filedata"]

for i, _ := range files {
        file, err := files[i].Open()
        defer file.Close()
    fh = getFileHash(file)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        break
    }

    dst, err := os.Create(baseDir+fh+".jpg")
    defer dst.Close()
    if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            break
    }

    if _, err := io.Copy(dst, file); err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                break
    }
}

getFileHash函数的内容如下:

func getFileHash (f *os.File) string {
     fstat, err := f.Stat()
     if err != nil {
    panic(err)
     }
     fSize := fstat.Size()
     buf := make([]byte, fSize)
     hash := sha1.New()
     n, err := f.Read(buf)
     if _, err := io.WriteString(hash, string(buf[:n])); err != nil {
           panic(err)
     }
     return string(hash.Sum(nil))
}

我收到以下错误,但我不确定如何解决此问题:

不能在函数参数中使用file(type multipart.File)作为类型* os.File:need type assertion

如果我使用样本哈希作为" fh "的值进行测试,它就可以了。

我知道我可以简单地保存文件,计算哈希值,然后移动文件,尽管我可以采取额外的步骤(如果可能的话)。我很感激你能给我的任何帮助。

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以同时将文件流式传输到磁盘和哈希函数。这是一个粗略的例子:

注意:它有一个警告:未对正在写入的文件检查错误。根据您的文件系统,这可能非常重要。您可能会在生产代码中考虑类似errutil的内容。

play link

package main

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

func shaAndSave(src io.Reader) ([]byte, error) {
    h := sha1.New()
    dest, err := os.Create("tmpfile.txt")
    if err != nil {
        return nil, err
    }
    defer dest.Close()
    t := io.TeeReader(src, h)
    _, err = io.Copy(dest, t)
    if err != nil {
        return nil, err
    }

    return h.Sum(nil), nil
}

func main() {
    src := strings.NewReader("pretend this was a file")

    hashBytes, err := shaAndSave(src)
    fmt.Printf("Returned %x and %v", hashBytes, err)
}

答案 1 :(得分:0)

来自http://golang.org/pkg/mime/multipart/#File

  

File是访问多部分消息的文件部分的接口。其内容可以存储在内存中或磁盘上。如果存储在磁盘上,File的底层具体类型将是* os.File。

所以你确实没有传递* os.File类型,因为它在内存中。尝试接受multipart.File作为类型。