logging.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package ftp
  2. import (
  3. "io"
  4. "os"
  5. "ftp-server/database"
  6. "github.com/spf13/afero"
  7. )
  8. // loggingFs 带日志功能的文件系统包装器
  9. type loggingFs struct {
  10. afero.Fs
  11. db *database.DB
  12. username string
  13. }
  14. // loggingFile 带日志功能的文件包装器
  15. type loggingFile struct {
  16. afero.File
  17. fs *loggingFs
  18. name string
  19. flags int
  20. written int64
  21. read int64
  22. logged bool
  23. }
  24. // newLoggingFs 创建带日志的文件系统
  25. func newLoggingFs(base afero.Fs, db *database.DB, username string) *loggingFs {
  26. return &loggingFs{
  27. Fs: base,
  28. db: db,
  29. username: username,
  30. }
  31. }
  32. // GetHandle 实现 ftpserverlib.ClientDriverExtentionFileTransfer 接口
  33. // flags: os.O_RDONLY 表示下载, os.O_WRONLY/os.O_CREATE 表示上传
  34. func (fs *loggingFs) GetHandle(name string, flags int, offset int64) (interface {
  35. io.Reader
  36. io.Writer
  37. io.Seeker
  38. io.Closer
  39. }, error) {
  40. file, err := fs.Fs.OpenFile(name, flags, 0666)
  41. if err != nil {
  42. return nil, err
  43. }
  44. // 如果有偏移量(断点续传),先 Seek
  45. if offset > 0 {
  46. if _, err := file.Seek(offset, 0); err != nil {
  47. file.Close()
  48. return nil, err
  49. }
  50. }
  51. return &loggingFile{
  52. File: file,
  53. fs: fs,
  54. name: name,
  55. flags: flags,
  56. logged: false,
  57. }, nil
  58. }
  59. func (f *loggingFile) Write(p []byte) (int, error) {
  60. n, err := f.File.Write(p)
  61. f.written += int64(n)
  62. return n, err
  63. }
  64. func (f *loggingFile) Read(p []byte) (int, error) {
  65. n, err := f.File.Read(p)
  66. f.read += int64(n)
  67. return n, err
  68. }
  69. func (f *loggingFile) Close() error {
  70. err := f.File.Close()
  71. // 避免重复记录
  72. if f.logged {
  73. return err
  74. }
  75. f.logged = true
  76. if f.fs.db == nil {
  77. return err
  78. }
  79. // 判断是上传还是下载
  80. isWrite := (f.flags & os.O_WRONLY) != 0 || (f.flags & os.O_RDWR) != 0 || (f.flags & os.O_CREATE) != 0
  81. if isWrite && f.written > 0 {
  82. f.fs.db.AddLog(&database.FTPLog{
  83. Username: f.fs.username,
  84. Action: "upload",
  85. FilePath: f.name,
  86. FileSize: f.written,
  87. Status: "success",
  88. })
  89. } else if !isWrite && f.read > 0 {
  90. f.fs.db.AddLog(&database.FTPLog{
  91. Username: f.fs.username,
  92. Action: "download",
  93. FilePath: f.name,
  94. FileSize: f.read,
  95. Status: "success",
  96. })
  97. }
  98. return err
  99. }