You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.1 KiB

4 years ago
4 years ago
4 years ago
  1. package cos
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "crypto/sha1"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "net/http"
  10. "net/url"
  11. "os"
  12. "strings"
  13. )
  14. // 单次上传文件最大为5GB
  15. const singleUploadMaxLength = 5 * 1024 * 1024 * 1024
  16. // 计算 md5 或 sha1 时的分块大小
  17. const calDigestBlockSize = 1024 * 1024 * 10
  18. func calMD5Digest(msg []byte) []byte {
  19. // TODO: 分块计算,减少内存消耗
  20. m := md5.New()
  21. m.Write(msg)
  22. return m.Sum(nil)
  23. }
  24. func calSHA1Digest(msg []byte) []byte {
  25. // TODO: 分块计算,减少内存消耗
  26. m := sha1.New()
  27. m.Write(msg)
  28. return m.Sum(nil)
  29. }
  30. // cloneRequest returns a clone of the provided *http.Request. The clone is a
  31. // shallow copy of the struct and its Header map.
  32. func cloneRequest(r *http.Request) *http.Request {
  33. // shallow copy of the struct
  34. r2 := new(http.Request)
  35. *r2 = *r
  36. // deep copy of the Header
  37. r2.Header = make(http.Header, len(r.Header))
  38. for k, s := range r.Header {
  39. r2.Header[k] = append([]string(nil), s...)
  40. }
  41. return r2
  42. }
  43. // encodeURIComponent like same function in javascript
  44. //
  45. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
  46. //
  47. // http://www.ecma-international.org/ecma-262/6.0/#sec-uri-syntax-and-semantics
  48. func encodeURIComponent(s string, excluded ...[]byte) string {
  49. var b bytes.Buffer
  50. written := 0
  51. for i, n := 0, len(s); i < n; i++ {
  52. c := s[i]
  53. switch c {
  54. case '-', '_', '.', '!', '~', '*', '\'', '(', ')':
  55. continue
  56. default:
  57. // Unreserved according to RFC 3986 sec 2.3
  58. if 'a' <= c && c <= 'z' {
  59. continue
  60. }
  61. if 'A' <= c && c <= 'Z' {
  62. continue
  63. }
  64. if '0' <= c && c <= '9' {
  65. continue
  66. }
  67. if len(excluded) > 0 {
  68. conti := false
  69. for _, ch := range excluded[0] {
  70. if ch == c {
  71. conti = true
  72. break
  73. }
  74. }
  75. if conti {
  76. continue
  77. }
  78. }
  79. }
  80. b.WriteString(s[written:i])
  81. fmt.Fprintf(&b, "%%%02X", c)
  82. written = i + 1
  83. }
  84. if written == 0 {
  85. return s
  86. }
  87. b.WriteString(s[written:])
  88. return b.String()
  89. }
  90. func decodeURIComponent(s string) (string, error) {
  91. decodeStr, err := url.QueryUnescape(s)
  92. if err != nil {
  93. return s, err
  94. }
  95. return decodeStr, err
  96. }
  97. func DecodeURIComponent(s string) (string, error) {
  98. return DecodeURIComponent(s)
  99. }
  100. func EncodeURIComponent(s string) string {
  101. return encodeURIComponent(s)
  102. }
  103. func GetReaderLen(reader io.Reader) (length int64, err error) {
  104. switch v := reader.(type) {
  105. case *bytes.Buffer:
  106. length = int64(v.Len())
  107. case *bytes.Reader:
  108. length = int64(v.Len())
  109. case *strings.Reader:
  110. length = int64(v.Len())
  111. case *os.File:
  112. stat, ferr := v.Stat()
  113. if ferr != nil {
  114. err = fmt.Errorf("can't get reader length: %s", ferr.Error())
  115. } else {
  116. length = stat.Size()
  117. }
  118. case *io.LimitedReader:
  119. length = int64(v.N)
  120. case FixedLengthReader:
  121. length = v.Size()
  122. default:
  123. err = fmt.Errorf("can't get reader content length, unkown reader type")
  124. }
  125. return
  126. }
  127. func CheckReaderLen(reader io.Reader) error {
  128. nlen, err := GetReaderLen(reader)
  129. if err != nil || nlen < singleUploadMaxLength {
  130. return nil
  131. }
  132. return errors.New("The single object size you upload can not be larger than 5GB")
  133. }