55 "mime/multipart"
66 "os"
77 "path/filepath"
8- "strings "
8+ "strconv "
99 "testing_system/common/config"
1010 "testing_system/lib/logger"
1111
@@ -21,25 +21,24 @@ func NewFilesystem(storageConfig *config.StorageConfig) IFilesystem {
2121 return & Filesystem {Basepath : storageConfig .StoragePath , BlockSize : storageConfig .BlockSize }
2222}
2323
24- func (filesystem * Filesystem ) generatePathFromID (prefix string , id string ) string {
25- var parts []string
26- parts = append (parts , prefix )
24+ func (filesystem * Filesystem ) generatePathFromID (id string ) string {
25+ parts := []string {}
2726 for i := 0 ; i < len (id ); i += int (filesystem .BlockSize ) {
2827 end := min (i + int (filesystem .BlockSize ), len (id ))
2928 parts = append (parts , id [i :end ])
3029 }
3130 return filepath .Join (parts ... )
3231}
3332
34- func (filesystem * Filesystem ) SaveFile (c * gin.Context , prefix string , id string , filename string , file * multipart.FileHeader ) error {
35- fullPath , err := filesystem .GetFilePath ( prefix , id , filename )
33+ func (filesystem * Filesystem ) SaveFile (c * gin.Context , resourceInfo * ResourceInfo , file * multipart.FileHeader ) error {
34+ fullPath , err := filesystem .BuildFilePath ( resourceInfo )
3635 if err != nil {
3736 return err
3837 }
3938
40- fullDirPath := filepath .Dir (fullPath )
41- if err := os .MkdirAll (fullDirPath , 0755 ); err != nil {
42- return fmt .Errorf ("failed to create directory: %w" , err )
39+ dir := filepath .Dir (fullPath )
40+ if err := os .MkdirAll (dir , 0755 ); err != nil {
41+ return fmt .Errorf ("failed to create directory %s : %w" , dir , err )
4342 }
4443
4544 if _ , err := os .Stat (fullPath ); err == nil {
@@ -49,8 +48,8 @@ func (filesystem *Filesystem) SaveFile(c *gin.Context, prefix string, id string,
4948 return c .SaveUploadedFile (file , fullPath )
5049}
5150
52- func (filesystem * Filesystem ) RemoveFile (prefix string , id string , filename string ) error {
53- fullPath , err := filesystem .GetFilePath ( prefix , id , filename )
51+ func (filesystem * Filesystem ) RemoveFile (resourceInfo * ResourceInfo ) error {
52+ fullPath , err := filesystem .BuildFilePath ( resourceInfo )
5453 if err != nil {
5554 return err
5655 }
@@ -60,16 +59,18 @@ func (filesystem *Filesystem) RemoveFile(prefix string, id string, filename stri
6059 }
6160
6261 dir := filepath .Dir (fullPath )
63- basePath , _ := filepath .Abs (filesystem .Basepath )
6462
6563 for {
66- absDir , _ := filepath .Abs (dir )
67- if absDir == basePath || ! strings .HasPrefix (absDir , basePath ) {
64+ if dir == filesystem .Basepath {
6865 break
6966 }
7067
7168 entries , err := os .ReadDir (dir )
72- if err != nil || len (entries ) > 0 {
69+
70+ if err != nil {
71+ return fmt .Errorf ("failed to read directory %s: %w" , dir , err )
72+ }
73+ if len (entries ) > 0 {
7374 break
7475 }
7576
@@ -82,28 +83,35 @@ func (filesystem *Filesystem) RemoveFile(prefix string, id string, filename stri
8283 return nil
8384}
8485
85- func (filesystem * Filesystem ) GetFilePath (prefix , id , filename string ) (string , error ) {
86- if prefix == "" || id == "" || filename == "" {
87- return "" , fmt .Errorf ("prefix, id, and filename cannot be empty" )
86+ func (filesystem * Filesystem ) GetFile (resourceInfo * ResourceInfo ) error {
87+ fullPath , err := filesystem .BuildFilePath (resourceInfo )
88+ if err != nil {
89+ return err
8890 }
8991
90- cleanFilename := filepath .Base (filename )
91-
92- subpath := filesystem .generatePathFromID (prefix , id )
93- fullPath := filepath .Join (filesystem .Basepath , subpath , cleanFilename )
92+ _ , err = os .Stat (fullPath )
9493
95- absBasepath , err := filepath .Abs (filesystem .Basepath )
9694 if err != nil {
97- return "" , err
95+ return err
9896 }
9997
100- absFullPath , err := filepath .Abs (fullPath )
101- if err != nil {
102- return "" , err
103- }
98+ return nil
99+ }
104100
105- if ! strings .HasPrefix (absFullPath , absBasepath ) {
106- return "" , fmt .Errorf ("invalid path: basepath is not a prefix of fullpath" )
101+ func (filesystem * Filesystem ) BuildFilePath (resourceInfo * ResourceInfo ) (string , error ) {
102+ subpathID := filesystem .generatePathFromID (strconv .FormatUint (resourceInfo .ID , 10 ))
103+ fullPath := filepath .Join (filesystem .Basepath , resourceInfo .DataType .String (), subpathID , resourceInfo .Filepath )
104+
105+ if resourceInfo .EmptyStorageFilename {
106+ entries , err := os .ReadDir (fullPath )
107+ if err != nil {
108+ return "" , fmt .Errorf ("failed to read directory %s: %v" , fullPath , err )
109+ }
110+ if len (entries ) != 1 || entries [0 ].IsDir () {
111+ return "" , fmt .Errorf ("StorageFilename is not specified, but directory %s does not contain exactly one file" , fullPath )
112+ }
113+ fullPath = filepath .Join (fullPath , entries [0 ].Name ())
114+ resourceInfo .Filepath = fullPath // It lets use resourceInfo.Filepath after successful SaveFile, RemoveFile and GetFile calls
107115 }
108116
109117 return fullPath , nil
0 commit comments