packer-cn/vendor/github.com/ufilesdk-dev/ufile-gosdk/utils.go

184 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ufsdk
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"time"
)
const (
blkSIZE = 2 << 21
)
//Config 配置文件序列化所需的全部字段
type Config struct {
PublicKey string `json:"public_key"`
PrivateKey string `json:"private_key"`
BucketName string `json:"bucket_name"`
FileHost string `json:"file_host"`
BucketHost string `json:"bucket_host"`
VerifyUploadMD5 bool `json:"verfiy_upload_md5"`
}
//LoadConfig 从配置文件加载一个配置。
func LoadConfig(jsonPath string) (*Config, error) {
file, err := openFile(jsonPath)
if err != nil {
return nil, err
}
defer file.Close()
configBytes, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
c := new(Config)
err = json.Unmarshal(configBytes, c)
if err != nil {
return nil, err
}
return c, nil
}
//VerifyHTTPCode 检查 HTTP 的返回值是否为 2XX如果不是就返回 false。
func VerifyHTTPCode(code int) bool {
if code < http.StatusOK || code > http.StatusIMUsed {
return false
}
return true
}
//GetFileMimeType 获取文件的 mime type 值,接收文件路径作为参数。如果检测不到,则返回空。
func GetFileMimeType(path string) string {
f, err := openFile(path)
if err != nil {
return ""
}
defer f.Close()
return getMimeType(f)
}
func getMimeType(f *os.File) string {
buffer := make([]byte, 512)
_, err := f.Read(buffer)
defer func() { f.Seek(0, 0) }() //revert file's seek
if err != nil {
return "plain/text"
}
return http.DetectContentType(buffer)
}
func openFile(path string) (*os.File, error) {
return os.Open(path)
}
//getFileSize get opened file size
func getFileSize(f *os.File) int64 {
fi, err := f.Stat()
if err != nil {
panic(err.Error())
}
return fi.Size()
}
//GetFileEtag 获取文件的 etag 值
func GetFileEtag(path string) string {
f, err := openFile(path)
if err != nil {
return ""
}
defer f.Close()
return calculateEtag(f)
}
//Calculatek 计算文件的 etag 值。
func calculateEtag(f *os.File) string {
fsize := getFileSize(f)
blkcnt := uint32(fsize / blkSIZE)
if fsize%blkSIZE != 0 {
blkcnt++
}
bs := make([]byte, 4)
binary.LittleEndian.PutUint32(bs, blkcnt)
h := sha1.New()
buf := make([]byte, 0, 24)
buf = append(buf, bs...)
if fsize <= blkSIZE {
io.Copy(h, f)
} else {
var i uint32
for i = 0; i < blkcnt; i++ {
shaBlk := sha1.New()
io.Copy(shaBlk, io.LimitReader(f, blkSIZE))
io.Copy(h, bytes.NewReader(shaBlk.Sum(nil)))
}
}
buf = h.Sum(buf)
etag := base64.URLEncoding.EncodeToString(buf)
return etag
}
func makeBoundry() string {
h := md5.New()
t := time.Now()
io.WriteString(h, t.String())
return fmt.Sprintf("%x", h.Sum(nil))
}
func makeFormBody(authorization, boundry, keyName, mimeType string, verifyMD5 bool, file *os.File) *bytes.Buffer {
boundry = "--" + boundry + "\r\n"
boundryBytes := []byte(boundry)
body := new(bytes.Buffer)
body.Write(boundryBytes)
body.Write(makeFormField("Authorization", authorization))
body.Write(boundryBytes)
body.Write(makeFormField("Content-Type", mimeType))
body.Write(boundryBytes)
body.Write(makeFormField("FileName", keyName))
body.Write(boundryBytes)
if verifyMD5 {
h := md5.New()
io.Copy(h, file)
md5Str := fmt.Sprintf("%x", h.Sum(nil))
body.Write(makeFormField("Content-MD5", md5Str))
body.Write(boundryBytes)
}
addtionalStr := fmt.Sprintf("Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n", keyName)
addtionalStr += fmt.Sprintf("Content-Type: %s\r\n\r\n", mimeType)
body.Write([]byte(addtionalStr))
body.ReadFrom(file)
body.Write([]byte("\r\n"))
body.Write(boundryBytes)
return body
}
func makeFormField(key, value string) []byte {
keyStr := fmt.Sprintf("Content-Disposition: form-data; name=\"%s\"\r\n\r\n", key)
valueStr := fmt.Sprintf("%s\r\n", value)
return []byte(keyStr + valueStr)
}
func structPrettyStr(data interface{}) string {
bytes, err := json.MarshalIndent(data, "", " ")
if err == nil {
return fmt.Sprintf("%s\n", bytes)
}
return ""
}