oss/lib/hash.go (149 lines of code) (raw):

package lib import ( "crypto/md5" "encoding/base64" "fmt" "hash" "hash/crc64" "io" "os" "strings" ) var specChineseHash = SpecText{ synopsisText: "计算本地文件的crc64或md5", paramText: "file_url [options]", syntaxText: ` ossutil hash file_url [--type=hashtype] `, detailHelpText: ` 该命令计算本地文件的crc64值或md5/content-md5值, 可以通过--type选项来控制计算的类型, 可选类型值为crc64或md5, 默认为` + DefaultHashType + `。 注意:oss文件的crc64和content-md5值一般可通过stat命令查看到,参考` + StatCRC64 + ` 字段和` + StatContentMD5 + `字段。若文件在oss支持crc64功能之前上传,则stat命令不支持查看crc64值; 对于append和multipart类型的文件,stat命令不支持查看content-md5值。 crc64的计算标准参考ECMA-182标准(http://www.ecma-international.org/publications/standards/Ecma-182.htm)。 计算类型为md5时,会同时输出文件的md5以及content-md5值。content-md5值其实是先计算md5 值获得128比特位数字,然后对该数字进行base64编码得到的值。关于content-md5的更多信息, 请参考https://tools.ietf.org/html/rfc1864。 用法: ossutil hash file_url [--type=hashtype] `, sampleText: ` 1) 计算本地文件的crc64: ossutil hash test.txt 或 ossutil hash test.txt --type=crc64 输出: CRC64-ECMA : 295992936743767023 2) 计算本地文件的md5: ossutil hash test.txt --type=md5 输出: MD5 : 01C3C45C03B2AF225EFAD9F911A33D73 Content-MD5 : AcPEXAOyryJe+tn5EaM9cw== `, } var specEnglishHash = SpecText{ synopsisText: "Get crc64 or md5 of local file", paramText: "file_url [options]", syntaxText: ` ossutil hash file_url [--type=hashtype] `, detailHelpText: ` The command calculate crc64 or md5/content-md5 value of the specified local file, specify the hashtype by --type, default hashtype is ` + DefaultHashType + `. Warning: user can use stat command to check the crc64 or md5/content-md5 value of normal oss object, see the ` + StatCRC64 + ` and ` + StatContentMD5 + ` field. If the object was uploaded to oss before oss support crc64 feature, stat result will not show ` + StatCRC64 + `, if the object is append file type or multipart, stat result will not show ` + StatContentMD5 + `. Crc64 is calcuated according to ECMA-182(http://www.ecma-international.org/publications/standards/Ecma-182.htm). When hashtype is md5, it will output both md5 and content-md5 of local file. Content-md5 is base64 encoded string of md5. For more detial about content-md5, please refer to https://tools.ietf.org/html/rfc1864. Usage: ossutil hash file_url [--type=hashtype] `, sampleText: ` 1) Get crc64 of local file: ossutil hash test.txt or ossutil hash test.txt --type=crc64 output: CRC64-ECMA : 295992936743767023 2) Get md5 of local file: ossutil hash test.txt --type=md5 output: MD5 : 01C3C45C03B2AF225EFAD9F911A33D73 Content-MD5 : AcPEXAOyryJe+tn5EaM9cw== `, } // HashCommand is the command to get crc64/md5 of local file type HashCommand struct { command Command } var hashCommand = HashCommand{ command: Command{ name: "hash", nameAlias: []string{""}, minArgc: 1, maxArgc: 1, specChinese: specChineseHash, specEnglish: specEnglishHash, group: GroupTypeAdditionalCommand, validOptionNames: []string{ OptionHashType, OptionLogLevel, }, }, } // function for RewriteLoadConfiger interface func (hc *HashCommand) rewriteLoadConfig(configFile string) error { // read config file, if error exist, do not print error var err error if hc.command.configOptions, err = LoadConfig(configFile); err != nil { hc.command.configOptions = OptionMapType{} } return nil } // function for FormatHelper interface func (hc *HashCommand) formatHelpForWhole() string { return hc.command.formatHelpForWhole() } func (hc *HashCommand) formatIndependHelp() string { return hc.command.formatIndependHelp() } // Init simulate inheritance, and polymorphism func (hc *HashCommand) Init(args []string, options OptionMapType) error { return hc.command.Init(args, options, hc) } // RunCommand simulate inheritance, and polymorphism func (hc *HashCommand) RunCommand() error { hashType, _ := GetString(OptionHashType, hc.command.options) path := hc.command.args[0] f, err := os.Open(path) if err != nil { return err } defer f.Close() f.Seek(0, os.SEEK_SET) switch strings.ToLower(hashType) { case MD5HashType: return hashMD5(f) default: return hashCRC64(f) } } func hashMD5(f io.Reader) error { md5Ins := md5.New() w, _ := md5Ins.(hash.Hash) if _, err := io.Copy(w, f); err != nil { return err } result := md5Ins.Sum(nil) fmt.Printf("%-28s: %X\n", HashMD5, result) encoded := base64.StdEncoding.EncodeToString(result) fmt.Printf("%-28s: %s\n", HashContentMD5, encoded) return nil } func hashCRC64(f io.Reader) error { crc64Ins := crc64.New(crc64.MakeTable(crc64.ECMA)) w, _ := crc64Ins.(hash.Hash) if _, err := io.Copy(w, f); err != nil { return err } result := crc64Ins.Sum64() fmt.Printf("%-28s: %d\n", HashCRC64, result) return nil }