github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgQiniu/Hash.go (about) 1 package kmgQiniu 2 3 import ( 4 "bytes" 5 "crypto/sha1" 6 "encoding/base64" 7 "io" 8 "os" 9 ) 10 11 const ( 12 hash_BLOCK_BITS = 22 // Indicate that the blocksize is 4M 13 hash_BLOCK_SIZE = 1 << hash_BLOCK_BITS 14 ) 15 16 func hashBlockCount(fsize int64) int { 17 18 return int((fsize + (hash_BLOCK_SIZE - 1)) >> hash_BLOCK_BITS) 19 } 20 21 func calSha1(b []byte, r io.Reader) ([]byte, error) { 22 23 h := sha1.New() 24 _, err := io.Copy(h, r) 25 if err != nil { 26 return nil, err 27 } 28 return h.Sum(b), nil 29 } 30 31 //计算从文件计算七牛hash值 32 func ComputeHashFromFile(filename string) (etag string, err error) { 33 f, err := os.Open(filename) 34 if err != nil { 35 return 36 } 37 defer f.Close() 38 39 fi, err := f.Stat() 40 if err != nil { 41 return 42 } 43 44 fsize := fi.Size() 45 blockCnt := hashBlockCount(fsize) 46 sha1Buf := make([]byte, 0, 21) 47 48 if blockCnt <= 1 { // file size <= 4M 49 sha1Buf = append(sha1Buf, 0x16) 50 sha1Buf, err = calSha1(sha1Buf, f) 51 if err != nil { 52 return 53 } 54 } else { // file size > 4M 55 sha1Buf = append(sha1Buf, 0x96) 56 sha1BlockBuf := make([]byte, 0, blockCnt*20) 57 for i := 0; i < blockCnt; i++ { 58 body := io.LimitReader(f, hash_BLOCK_SIZE) 59 sha1BlockBuf, err = calSha1(sha1BlockBuf, body) 60 if err != nil { 61 return 62 } 63 } 64 sha1Buf, _ = calSha1(sha1Buf, bytes.NewReader(sha1BlockBuf)) 65 } 66 etag = base64.URLEncoding.EncodeToString(sha1Buf) 67 return 68 } 69 70 func ComputeHashFromBytes(b []byte) (etag string) { 71 f := bytes.NewReader(b) 72 blockCnt := hashBlockCount(int64(len(b))) 73 sha1Buf := make([]byte, 0, 21) 74 75 var err error 76 if blockCnt <= 1 { // file size <= 4M 77 sha1Buf = append(sha1Buf, 0x16) 78 sha1Buf, err = calSha1(sha1Buf, f) 79 if err != nil { 80 panic(err) 81 } 82 } else { // file size > 4M 83 sha1Buf = append(sha1Buf, 0x96) 84 sha1BlockBuf := make([]byte, 0, blockCnt*20) 85 for i := 0; i < blockCnt; i++ { 86 body := io.LimitReader(f, hash_BLOCK_SIZE) 87 sha1BlockBuf, err = calSha1(sha1BlockBuf, body) 88 if err != nil { 89 panic(err) 90 } 91 } 92 sha1Buf, _ = calSha1(sha1Buf, bytes.NewReader(sha1BlockBuf)) 93 } 94 etag = base64.URLEncoding.EncodeToString(sha1Buf) 95 return 96 }