55 "mime/multipart"
66 "os"
77 "path/filepath"
8+ "strconv"
89 "strings"
910 "testing_system/common/config"
1011 "testing_system/lib/logger"
@@ -22,24 +23,34 @@ func NewFilesystem(storageConfig *config.StorageConfig) IFilesystem {
2223}
2324
2425func (filesystem * Filesystem ) generatePathFromID (prefix string , id string ) string {
25- var parts []string
26- parts = append (parts , prefix )
26+ parts := []string {prefix }
2727 for i := 0 ; i < len (id ); i += int (filesystem .BlockSize ) {
2828 end := min (i + int (filesystem .BlockSize ), len (id ))
2929 parts = append (parts , id [i :end ])
3030 }
3131 return filepath .Join (parts ... )
3232}
3333
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 )
34+ func (filesystem * Filesystem ) SaveFile (c * gin.Context , resourceInfo * ResourceInfo , file * multipart.FileHeader ) error {
35+ fullPath , err := filesystem .BuildFilePath ( resourceInfo )
3636 if err != nil {
3737 return err
3838 }
3939
40- fullDirPath := filepath .Dir (fullPath )
41- if err := os .MkdirAll (fullDirPath , 0755 ); err != nil {
42- return fmt .Errorf ("failed to create directory: %w" , err )
40+ dir := filepath .Dir (fullPath )
41+ if err := os .MkdirAll (dir , 0755 ); err != nil {
42+ return fmt .Errorf ("failed to create directory %s: %w" , dir , err )
43+ }
44+
45+ entries , err := filesystem .GetDirEntriesNames (dir )
46+ if err != nil {
47+ return err
48+ }
49+
50+ if resourceInfo .EmptyStorageFilename {
51+ if len (entries ) > 1 || (len (entries ) == 1 && entries [0 ] != filepath .Base (resourceInfo .Filepath )) {
52+ return fmt .Errorf ("failed to save file: directory %s already contains some files different from default filename, but StorageFilename is not specified" , dir )
53+ }
4354 }
4455
4556 if _ , err := os .Stat (fullPath ); err == nil {
@@ -49,17 +60,28 @@ func (filesystem *Filesystem) SaveFile(c *gin.Context, prefix string, id string,
4960 return c .SaveUploadedFile (file , fullPath )
5061}
5162
52- func (filesystem * Filesystem ) RemoveFile (prefix string , id string , filename string ) error {
53- fullPath , err := filesystem .GetFilePath (prefix , id , filename )
63+ func (filesystem * Filesystem ) RemoveFile (resourceInfo * ResourceInfo ) error {
64+ fullPath , err := filesystem .BuildFilePath (resourceInfo )
65+ if err != nil {
66+ return err
67+ }
68+
69+ dir := filepath .Dir (fullPath )
70+ entries , err := filesystem .GetDirEntriesNames (dir )
5471 if err != nil {
5572 return err
5673 }
5774
75+ if resourceInfo .EmptyStorageFilename {
76+ if len (entries ) > 1 || (len (entries ) == 1 && entries [0 ] != filepath .Base (resourceInfo .Filepath )) {
77+ return fmt .Errorf ("failed to remove file: directory %s contains some files different from default filename, but StorageFilename is not specified" , dir )
78+ }
79+ }
80+
5881 if err := os .Remove (fullPath ); err != nil {
5982 return fmt .Errorf ("failed to remove file %s: %w" , fullPath , err )
6083 }
6184
62- dir := filepath .Dir (fullPath )
6385 basePath , _ := filepath .Abs (filesystem .Basepath )
6486
6587 for {
@@ -82,15 +104,38 @@ func (filesystem *Filesystem) RemoveFile(prefix string, id string, filename stri
82104 return nil
83105}
84106
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" )
107+ func (filesystem * Filesystem ) GetFile (resourceInfo * ResourceInfo ) (string , error ) {
108+ fullPath , err := filesystem .BuildFilePath (resourceInfo )
109+ if err != nil {
110+ return "" , err
88111 }
89112
90- cleanFilename := filepath .Base (filename )
113+ dir := filepath .Dir (fullPath )
114+ entries , err := filesystem .GetDirEntriesNames (dir )
115+ if err != nil {
116+ return "" , err
117+ }
118+
119+ if resourceInfo .EmptyStorageFilename {
120+ if len (entries ) > 1 || (len (entries ) == 1 && entries [0 ] != filepath .Base (resourceInfo .Filepath )) {
121+ return "" , fmt .Errorf ("failed to get file: directory %s contains some files different from default filename, but StorageFilename is not specified" , dir )
122+ }
123+ }
124+
125+ _ , err = os .Stat (fullPath )
91126
92- subpath := filesystem .generatePathFromID (prefix , id )
93- fullPath := filepath .Join (filesystem .Basepath , subpath , cleanFilename )
127+ if err != nil {
128+ return "" , err
129+ }
130+
131+ return fullPath , nil
132+ }
133+
134+ func (filesystem * Filesystem ) BuildFilePath (resourceInfo * ResourceInfo ) (string , error ) {
135+ cleanFilename := filepath .Base (resourceInfo .Filepath )
136+
137+ subpathID := filesystem .generatePathFromID (resourceInfo .DataType .String (), strconv .FormatUint (resourceInfo .ID , 10 ))
138+ fullPath := filepath .Join (filesystem .Basepath , subpathID , cleanFilename )
94139
95140 absBasepath , err := filepath .Abs (filesystem .Basepath )
96141 if err != nil {
@@ -103,8 +148,23 @@ func (filesystem *Filesystem) GetFilePath(prefix, id, filename string) (string,
103148 }
104149
105150 if ! strings .HasPrefix (absFullPath , absBasepath ) {
106- return "" , fmt .Errorf ("invalid path: basepath is not a prefix of fullpath" )
151+ return "" , fmt .Errorf ("invalid path: filesystem basepath is not a prefix of file fullpath" )
107152 }
108153
109154 return fullPath , nil
110155}
156+
157+ func (filesystem * Filesystem ) GetDirEntriesNames (dir string ) ([]string , error ) {
158+ entries , err := os .ReadDir (dir )
159+ if err != nil {
160+ return nil , fmt .Errorf ("failed to read directory %s: %v" , dir , err )
161+ }
162+
163+ names := make ([]string , 0 , len (entries ))
164+
165+ for _ , entry := range entries {
166+ names = append (names , entry .Name ())
167+ }
168+
169+ return names , nil
170+ }
0 commit comments