记又拍云接入过程
更新于 阅读 2 次
首先吐槽一下又拍云的文档,需要有亿点改进。
由于我是前端上传,官网没有js sdk,所以需要结合后端来生成签名和policy。
前端使用的是form api的方式上传。
后端
直接上后端代码(golang):
package application import ( "crypto/hmac" "crypto/md5" "crypto/sha1" "encoding/base64" "encoding/json" "fmt" "strings" "time" ) type Upyun struct { Token string `json:"token"` Date string `json:"date"` Policy string `json:"policy"` } func makeSaveKey() string { return "/{year}/{mon}/{day}/upload_{random32}{.suffix}" } func makePolicy(bucket, saveKey string) string { // 过期时间设置为一天。 expiration := time.Now().AddDate(0, 0, 1).Unix() obj := struct { Bucket string `json:"bucket"` SaveKey string `json:"save-key"` Expiration int64 `json:"expiration"` // Date string `json:"date"` }{ Bucket: bucket, SaveKey: saveKey, Expiration: expiration, // Date: date, } str, err := json.Marshal(&obj) if err != nil { return "" } sEnc := base64.StdEncoding.EncodeToString([]byte(str)) return sEnc } func md5Str(s string) string { return fmt.Sprintf("%x", md5.Sum([]byte(s))) } func makeRFC1123Date(d time.Time) string { utc := d.UTC().Format(time.RFC1123) return strings.Replace(utc, "UTC", "GMT", -1) } func base64ToStr(b []byte) string { return base64.StdEncoding.EncodeToString(b) } func sign(key, secret, method, uri, date, policy, md5 string) string { mac := hmac.New(sha1.New, []byte(secret)) elems := []string{} for _, v := range []string{method, uri, date, policy, md5} { if v != "" { elems = append(elems, v) } } value := strings.Join(elems, "&") mac.Write([]byte(value)) signStr := base64ToStr(mac.Sum(nil)) return "UPYUN " + key + ":" + signStr } func GetUpyunToken(key, secret, bucket, method string) *Upyun { date := makeRFC1123Date(time.Now()) saveKey := makeSaveKey() policy := makePolicy(bucket, saveKey) token := sign(key, md5Str(secret), method, "/"+bucket, "", policy, "") upyun := Upyun{ Date: date, Token: token, Policy: policy, } return &upyun }
说说遇到的坑,
-
签名和policy中不要设置date数据,不然前端上传时的时间与签名和policy中的时间对不上。
-
调用sign方法时method参数后一个参数在拼接时需要加上/,不然签名不对,比如下面这样。
method&/uri&policy
上面的问题是在客服技术人员的耐心指导下调通的。在此感谢技术大佬。
前端
前端使用的antd的upload组件,
<Upload name="file" method={'POST'} listType="picture-card" className="avatar-uploader" showUploadList={false} action={`https://v0.api.upyun.com/${bucketName}`} beforeUpload={beforeUpload} onChange={handleChange} data={{ authorization: xxxx, policy: xxx, }} > {value ? <img src={value} alt="avatar" style={{width: '100%'}} /> : uploadButton} </Upload>
由于签名需要涉及到密码,放在服务器上生成比较安全,前端使用即可。