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.

149 lines
3.5 KiB

4 years ago
4 years ago
4 years ago
  1. package cos
  2. import (
  3. "fmt"
  4. "hash"
  5. "io"
  6. )
  7. type ProgressEventType int
  8. const (
  9. // 数据开始传输
  10. ProgressStartedEvent ProgressEventType = iota
  11. // 数据传输中
  12. ProgressDataEvent
  13. // 数据传输完成, 但不能表示对应API调用完成
  14. ProgressCompletedEvent
  15. // 只有在数据传输时发生错误才会返回
  16. ProgressFailedEvent
  17. )
  18. type ProgressEvent struct {
  19. EventType ProgressEventType
  20. RWBytes int64
  21. ConsumedBytes int64
  22. TotalBytes int64
  23. Err error
  24. }
  25. func newProgressEvent(eventType ProgressEventType, rwBytes, consumed, total int64, err ...error) *ProgressEvent {
  26. event := &ProgressEvent{
  27. EventType: eventType,
  28. RWBytes: rwBytes,
  29. ConsumedBytes: consumed,
  30. TotalBytes: total,
  31. }
  32. if len(err) > 0 {
  33. event.Err = err[0]
  34. }
  35. return event
  36. }
  37. // 用户自定义Listener需要实现该方法
  38. type ProgressListener interface {
  39. ProgressChangedCallback(event *ProgressEvent)
  40. }
  41. func progressCallback(listener ProgressListener, event *ProgressEvent) {
  42. if listener != nil && event != nil {
  43. listener.ProgressChangedCallback(event)
  44. }
  45. }
  46. type teeReader struct {
  47. reader io.Reader
  48. writer io.Writer
  49. consumedBytes int64
  50. totalBytes int64
  51. listener ProgressListener
  52. }
  53. func (r *teeReader) Read(p []byte) (int, error) {
  54. if r.consumedBytes == 0 {
  55. event := newProgressEvent(ProgressStartedEvent, 0, r.consumedBytes, r.totalBytes)
  56. progressCallback(r.listener, event)
  57. }
  58. n, err := r.reader.Read(p)
  59. if err != nil && err != io.EOF {
  60. event := newProgressEvent(ProgressFailedEvent, 0, r.consumedBytes, r.totalBytes, err)
  61. progressCallback(r.listener, event)
  62. }
  63. if n > 0 {
  64. r.consumedBytes += int64(n)
  65. if r.writer != nil {
  66. if n, err := r.writer.Write(p[:n]); err != nil {
  67. return n, err
  68. }
  69. }
  70. if r.listener != nil {
  71. event := newProgressEvent(ProgressDataEvent, int64(n), r.consumedBytes, r.totalBytes)
  72. progressCallback(r.listener, event)
  73. }
  74. }
  75. if err == io.EOF {
  76. event := newProgressEvent(ProgressCompletedEvent, int64(n), r.consumedBytes, r.totalBytes)
  77. progressCallback(r.listener, event)
  78. }
  79. return n, err
  80. }
  81. func (r *teeReader) Close() error {
  82. if rc, ok := r.reader.(io.ReadCloser); ok {
  83. return rc.Close()
  84. }
  85. return nil
  86. }
  87. func (r *teeReader) Size() int64 {
  88. return r.totalBytes
  89. }
  90. func (r *teeReader) Crc64() uint64 {
  91. if r.writer != nil {
  92. if th, ok := r.writer.(hash.Hash64); ok {
  93. return th.Sum64()
  94. }
  95. }
  96. return 0
  97. }
  98. func TeeReader(reader io.Reader, writer io.Writer, total int64, listener ProgressListener) *teeReader {
  99. return &teeReader{
  100. reader: reader,
  101. writer: writer,
  102. consumedBytes: 0,
  103. totalBytes: total,
  104. listener: listener,
  105. }
  106. }
  107. type FixedLengthReader interface {
  108. io.Reader
  109. Size() int64
  110. }
  111. type DefaultProgressListener struct {
  112. }
  113. func (l *DefaultProgressListener) ProgressChangedCallback(event *ProgressEvent) {
  114. switch event.EventType {
  115. case ProgressStartedEvent:
  116. fmt.Printf("Transfer Start [ConsumedBytes/TotalBytes: %d/%d]\n",
  117. event.ConsumedBytes, event.TotalBytes)
  118. case ProgressDataEvent:
  119. fmt.Printf("\rTransfer Data [ConsumedBytes/TotalBytes: %d/%d, %d%%]",
  120. event.ConsumedBytes, event.TotalBytes, event.ConsumedBytes*100/event.TotalBytes)
  121. case ProgressCompletedEvent:
  122. fmt.Printf("\nTransfer Complete [ConsumedBytes/TotalBytes: %d/%d]\n",
  123. event.ConsumedBytes, event.TotalBytes)
  124. case ProgressFailedEvent:
  125. fmt.Printf("\nTransfer Failed [ConsumedBytes/TotalBytes: %d/%d] [Err: %v]\n",
  126. event.ConsumedBytes, event.TotalBytes, event.Err)
  127. default:
  128. fmt.Printf("Progress Changed Error: unknown progress event type\n")
  129. }
  130. }