file.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package httpd
  2. import (
  3. "errors"
  4. "io"
  5. "sync/atomic"
  6. "github.com/eikenb/pipeat"
  7. "github.com/drakkan/sftpgo/common"
  8. )
  9. var errTransferAborted = errors.New("transfer aborted")
  10. type httpdFile struct {
  11. *common.BaseTransfer
  12. reader io.ReadCloser
  13. isFinished bool
  14. }
  15. func newHTTPDFile(baseTransfer *common.BaseTransfer, pipeReader *pipeat.PipeReaderAt) *httpdFile {
  16. var reader io.ReadCloser
  17. if baseTransfer.File != nil {
  18. reader = baseTransfer.File
  19. } else if pipeReader != nil {
  20. reader = pipeReader
  21. }
  22. return &httpdFile{
  23. BaseTransfer: baseTransfer,
  24. reader: reader,
  25. isFinished: false,
  26. }
  27. }
  28. // Read reads the contents to downloads.
  29. func (f *httpdFile) Read(p []byte) (n int, err error) {
  30. if atomic.LoadInt32(&f.AbortTransfer) == 1 {
  31. return 0, errTransferAborted
  32. }
  33. f.Connection.UpdateLastActivity()
  34. n, err = f.reader.Read(p)
  35. atomic.AddInt64(&f.BytesSent, int64(n))
  36. if err != nil && err != io.EOF {
  37. f.TransferError(err)
  38. return
  39. }
  40. f.HandleThrottle()
  41. return
  42. }
  43. // Close closes the current transfer
  44. func (f *httpdFile) Close() error {
  45. if err := f.setFinished(); err != nil {
  46. return err
  47. }
  48. err := f.closeIO()
  49. errBaseClose := f.BaseTransfer.Close()
  50. if errBaseClose != nil {
  51. err = errBaseClose
  52. }
  53. return f.Connection.GetFsError(f.Fs, err)
  54. }
  55. func (f *httpdFile) closeIO() error {
  56. var err error
  57. if f.File != nil {
  58. err = f.File.Close()
  59. } else if f.reader != nil {
  60. err = f.reader.Close()
  61. }
  62. return err
  63. }
  64. func (f *httpdFile) setFinished() error {
  65. f.Lock()
  66. defer f.Unlock()
  67. if f.isFinished {
  68. return common.ErrTransferClosed
  69. }
  70. f.isFinished = true
  71. return nil
  72. }