bokodir.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package bokothumb
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "golang.org/x/net/webdav"
  9. "imuslab.com/bokofs/bokofsd/mod/renderer"
  10. )
  11. /*
  12. bokodir.go
  13. The bokodir implements a disk based file system from the webdav.FileSystem interface
  14. A file in this implementation corrisponding to a real file on disk
  15. */
  16. type Resolutions struct {
  17. Width int
  18. Height int
  19. }
  20. type RouterDir struct {
  21. Prefix string //Path prefix to trim, usually is the root path of the worker
  22. ThumbStore string //Path to the thumbnail store
  23. FsPath string //Disk path for the corrisponding file system to create thumbnail
  24. /* Private Properties */
  25. renderer *renderer.RenderHandler
  26. dir webdav.Dir
  27. }
  28. // CreateThumbnailRenderer creates a new thumbnail renderer from a directory
  29. func CreateThumbnailRenderer(thumbDir string, sourceFsDir string, prefix string, readonly bool) (*RouterDir, error) {
  30. if _, err := os.Stat(sourceFsDir); os.IsNotExist(err) {
  31. //Check if the sourceFsDir is a valid directory
  32. return nil, err
  33. }
  34. //Initiate the dir
  35. fs := webdav.Dir(thumbDir)
  36. //Create the thumbnail store if it does not exist
  37. if err := os.MkdirAll(thumbDir, 0755); err != nil {
  38. return nil, err
  39. }
  40. //Create the renderer
  41. thumbrRenderer := renderer.NewRenderHandler()
  42. return &RouterDir{
  43. Prefix: prefix,
  44. ThumbStore: thumbDir,
  45. FsPath: sourceFsDir,
  46. renderer: thumbrRenderer,
  47. dir: fs,
  48. }, nil
  49. }
  50. func (r *RouterDir) cleanPrefix(name string) string {
  51. name = filepath.ToSlash(filepath.Clean(name))
  52. fmt.Println("[Bokothumb]", r.Prefix, name, strings.TrimPrefix(name, r.Prefix))
  53. return strings.TrimPrefix(name, r.Prefix)
  54. }
  55. func (r *RouterDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
  56. // Implement the Mkdir method
  57. return webdav.ErrForbidden
  58. }
  59. func (r *RouterDir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
  60. // Implement the OpenFile method
  61. name = r.cleanPrefix(name)
  62. ext := filepath.Ext(name)
  63. if ext == "" {
  64. //Requested a folder path. Render the content
  65. contents, err := os.ReadDir(filepath.Join(r.FsPath, name))
  66. if err != nil {
  67. return nil, err
  68. }
  69. //Start thumbnail rendering in background
  70. outputFolder := filepath.Join(r.ThumbStore, name)
  71. for _, entry := range contents {
  72. if entry.IsDir() {
  73. os.MkdirAll(filepath.Join(outputFolder, entry.Name()), 0755)
  74. continue
  75. }
  76. go func() {
  77. r.renderer.RenderThumbnail(filepath.Join(r.FsPath, name, entry.Name()), outputFolder)
  78. }()
  79. }
  80. } else {
  81. //Requested a file path. Render the thumbnail
  82. outputFolder := filepath.Join(r.ThumbStore, filepath.Dir(name))
  83. if err := os.MkdirAll(filepath.Dir(outputFolder), 0755); err != nil {
  84. return nil, err
  85. }
  86. //The RenderThumbnail function will immeidiately return if the thumbnail already exists
  87. //If the thumbnail is not present, it will be generated in real time
  88. r.renderer.RenderThumbnail(filepath.Join(r.FsPath, name), outputFolder)
  89. }
  90. fmt.Println("[Bokothumb]", "OpenFile called to "+name)
  91. // Check if the file is being opened with write permissions
  92. if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
  93. return nil, webdav.ErrForbidden
  94. }
  95. return r.dir.OpenFile(ctx, name, flag, perm)
  96. }
  97. func (r *RouterDir) RemoveAll(ctx context.Context, name string) error {
  98. // Implement the RemoveAll method
  99. name = r.cleanPrefix(name)
  100. fmt.Println("[Bokothumb]", "RemoveAll called to "+name)
  101. return r.dir.RemoveAll(ctx, name)
  102. }
  103. func (r *RouterDir) Rename(ctx context.Context, oldName, newName string) error {
  104. // Implement the Rename method
  105. return webdav.ErrForbidden
  106. }
  107. func (r *RouterDir) Stat(ctx context.Context, name string) (os.FileInfo, error) {
  108. // Implement the Stat method
  109. name = r.cleanPrefix(name)
  110. fmt.Println("[Bokothumb]", "Stat called to "+name)
  111. return r.dir.Stat(ctx, name)
  112. }
  113. // Ensure RouterDir implements the FileSystem interface
  114. var _ webdav.FileSystem = (*RouterDir)(nil)