bfs.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package dao
  2. import (
  3. "context"
  4. "crypto/hmac"
  5. "crypto/sha1"
  6. "encoding/base64"
  7. "errors"
  8. "fmt"
  9. "hash"
  10. "io"
  11. "net/http"
  12. "strconv"
  13. "time"
  14. "go-common/library/ecode"
  15. "go-common/library/log"
  16. )
  17. var (
  18. errUpload = errors.New("Upload failed")
  19. )
  20. // Upload upload bfs.
  21. func (d *Dao) Upload(c context.Context, fileType string, filename string, body io.Reader) (location string, err error) {
  22. req, err := http.NewRequest(d.c.BFS.Method, d.c.BFS.URL+filename, body)
  23. if err != nil {
  24. log.Error("http.NewRequest error (%v) | fileType(%s)", err, fileType)
  25. return
  26. }
  27. expire := time.Now().Unix()
  28. authorization := authorize(d.c.BFS.Key, d.c.BFS.Secret, d.c.BFS.Method, d.c.BFS.Bucket, filename, expire)
  29. req.Header.Set("Host", d.c.BFS.Host)
  30. req.Header.Add("Date", fmt.Sprint(expire))
  31. req.Header.Add("Authorization", authorization)
  32. req.Header.Add("Content-Type", fileType)
  33. // timeout
  34. ctx, cancel := context.WithTimeout(c, time.Duration(d.c.BFS.Timeout))
  35. req = req.WithContext(ctx)
  36. defer cancel()
  37. resp, err := d.client.Do(req)
  38. if err != nil {
  39. log.Error("d.Client.Do error(%v) | url(%s)", err, d.c.BFS.URL+filename)
  40. err = ecode.BfsUploadServiceUnavailable
  41. return
  42. }
  43. if resp.StatusCode != http.StatusOK {
  44. log.Error("Upload http.StatusCode nq http.StatusOK (%d) | url(%s)", resp.StatusCode, d.c.BFS.URL+filename)
  45. err = errUpload
  46. return
  47. }
  48. header := resp.Header
  49. code := header.Get("Code")
  50. if code != strconv.Itoa(http.StatusOK) {
  51. log.Error("strconv.Itoa err, code(%s) | url(%s)", code, d.c.BFS.URL+filename)
  52. err = errUpload
  53. return
  54. }
  55. location = header.Get("Location")
  56. return
  57. }
  58. // authorize returns authorization for upload file to bfs
  59. func authorize(key, secret, method, bucket string, fname string, expire int64) (authorization string) {
  60. var (
  61. content string
  62. mac hash.Hash
  63. signature string
  64. )
  65. content = fmt.Sprintf("%s\n%s\n%s\n%d\n", method, bucket, fname, expire)
  66. mac = hmac.New(sha1.New, []byte(secret))
  67. mac.Write([]byte(content))
  68. signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
  69. authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
  70. return
  71. }