utils.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package oss
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "hash/crc64"
  7. "net/http"
  8. "os"
  9. "os/exec"
  10. "runtime"
  11. "time"
  12. )
  13. // Get User Agent
  14. // Go sdk相关信息,包括sdk版本,操作系统类型,GO版本
  15. var userAgent = func() string {
  16. sys := getSysInfo()
  17. return fmt.Sprintf("aliyun-sdk-go/%s (%s/%s/%s;%s)", Version, sys.name,
  18. sys.release, sys.machine, runtime.Version())
  19. }()
  20. type sysInfo struct {
  21. name string // 操作系统名称windows/Linux
  22. release string // 操作系统版本 2.6.32-220.23.2.ali1089.el5.x86_64等
  23. machine string // 机器类型amd64/x86_64
  24. }
  25. // Get system info
  26. // 获取操作系统信息、机器类型
  27. func getSysInfo() sysInfo {
  28. name := runtime.GOOS
  29. release := "-"
  30. machine := runtime.GOARCH
  31. if out, err := exec.Command("uname", "-s").CombinedOutput(); err == nil {
  32. name = string(bytes.TrimSpace(out))
  33. }
  34. if out, err := exec.Command("uname", "-r").CombinedOutput(); err == nil {
  35. release = string(bytes.TrimSpace(out))
  36. }
  37. if out, err := exec.Command("uname", "-m").CombinedOutput(); err == nil {
  38. machine = string(bytes.TrimSpace(out))
  39. }
  40. return sysInfo{name: name, release: release, machine: machine}
  41. }
  42. // GetNowSec returns Unix time, the number of seconds elapsed since January 1, 1970 UTC.
  43. // 获取当前时间,从UTC开始的秒数。
  44. func GetNowSec() int64 {
  45. return time.Now().Unix()
  46. }
  47. // GetNowNanoSec returns t as a Unix time, the number of nanoseconds elapsed
  48. // since January 1, 1970 UTC. The result is undefined if the Unix time
  49. // in nanoseconds cannot be represented by an int64. Note that this
  50. // means the result of calling UnixNano on the zero Time is undefined.
  51. // 获取当前时间,从UTC开始的纳秒。
  52. func GetNowNanoSec() int64 {
  53. return time.Now().UnixNano()
  54. }
  55. // GetNowGMT 获取当前时间,格式形如"Mon, 02 Jan 2006 15:04:05 GMT",HTTP中使用的时间格式
  56. func GetNowGMT() string {
  57. return time.Now().UTC().Format(http.TimeFormat)
  58. }
  59. // FileChunk 文件片定义
  60. type FileChunk struct {
  61. Number int // 块序号
  62. Offset int64 // 块在文件中的偏移量
  63. Size int64 // 块大小
  64. }
  65. // SplitFileByPartNum Split big file to part by the num of part
  66. // 按指定的块数分割文件。返回值FileChunk为分割结果,error为nil时有效。
  67. func SplitFileByPartNum(fileName string, chunkNum int) ([]FileChunk, error) {
  68. if chunkNum <= 0 || chunkNum > 10000 {
  69. return nil, errors.New("chunkNum invalid")
  70. }
  71. file, err := os.Open(fileName)
  72. if err != nil {
  73. return nil, err
  74. }
  75. defer file.Close()
  76. stat, err := file.Stat()
  77. if err != nil {
  78. return nil, err
  79. }
  80. if int64(chunkNum) > stat.Size() {
  81. return nil, errors.New("oss: chunkNum invalid")
  82. }
  83. var chunks []FileChunk
  84. var chunk = FileChunk{}
  85. var chunkN = (int64)(chunkNum)
  86. for i := int64(0); i < chunkN; i++ {
  87. chunk.Number = int(i + 1)
  88. chunk.Offset = i * (stat.Size() / chunkN)
  89. if i == chunkN-1 {
  90. chunk.Size = stat.Size()/chunkN + stat.Size()%chunkN
  91. } else {
  92. chunk.Size = stat.Size() / chunkN
  93. }
  94. chunks = append(chunks, chunk)
  95. }
  96. return chunks, nil
  97. }
  98. // SplitFileByPartSize Split big file to part by the size of part
  99. // 按块大小分割文件。返回值FileChunk为分割结果,error为nil时有效。
  100. func SplitFileByPartSize(fileName string, chunkSize int64) ([]FileChunk, error) {
  101. if chunkSize <= 0 {
  102. return nil, errors.New("chunkSize invalid")
  103. }
  104. file, err := os.Open(fileName)
  105. if err != nil {
  106. return nil, err
  107. }
  108. defer file.Close()
  109. stat, err := file.Stat()
  110. if err != nil {
  111. return nil, err
  112. }
  113. var chunkN = stat.Size() / chunkSize
  114. if chunkN >= 10000 {
  115. return nil, errors.New("Too many parts, please increase part size.")
  116. }
  117. var chunks []FileChunk
  118. var chunk = FileChunk{}
  119. for i := int64(0); i < chunkN; i++ {
  120. chunk.Number = int(i + 1)
  121. chunk.Offset = i * chunkSize
  122. chunk.Size = chunkSize
  123. chunks = append(chunks, chunk)
  124. }
  125. if stat.Size()%chunkSize > 0 {
  126. chunk.Number = len(chunks) + 1
  127. chunk.Offset = int64(len(chunks)) * chunkSize
  128. chunk.Size = stat.Size() % chunkSize
  129. chunks = append(chunks, chunk)
  130. }
  131. return chunks, nil
  132. }
  133. // GetPartEnd 计算结束位置
  134. func GetPartEnd(begin int64, total int64, per int64) int64 {
  135. if begin+per > total {
  136. return total - 1
  137. }
  138. return begin + per - 1
  139. }
  140. // crcTable returns the Table constructed from the specified polynomial
  141. var crcTable = func() *crc64.Table {
  142. return crc64.MakeTable(crc64.ECMA)
  143. }