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.

139 lines
3.4 KiB

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