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 )
5465 if err != nil {
5566 return err
5667 }
5768
69+ dir := filepath .Dir (fullPath )
70+ entries , err := filesystem .GetDirEntriesNames (dir )
71+ if err != nil {
72+ return err
73+ }
74+
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,32 @@ 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
111+ }
112+
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+ }
88123 }
89124
90- cleanFilename := filepath .Base (filename )
125+ return fullPath , nil
126+ }
91127
92- subpath := filesystem .generatePathFromID (prefix , id )
93- fullPath := filepath .Join (filesystem .Basepath , subpath , cleanFilename )
128+ func (filesystem * Filesystem ) BuildFilePath (resourceInfo * ResourceInfo ) (string , error ) {
129+ cleanFilename := filepath .Base (resourceInfo .Filepath )
130+
131+ subpathID := filesystem .generatePathFromID (resourceInfo .DataType .String (), strconv .FormatUint (resourceInfo .ID , 10 ))
132+ fullPath := filepath .Join (filesystem .Basepath , subpathID , cleanFilename )
94133
95134 absBasepath , err := filepath .Abs (filesystem .Basepath )
96135 if err != nil {
@@ -103,8 +142,23 @@ func (filesystem *Filesystem) GetFilePath(prefix, id, filename string) (string,
103142 }
104143
105144 if ! strings .HasPrefix (absFullPath , absBasepath ) {
106- return "" , fmt .Errorf ("invalid path: basepath is not a prefix of fullpath" )
145+ return "" , fmt .Errorf ("invalid path: filesystem basepath is not a prefix of file fullpath" )
107146 }
108147
109148 return fullPath , nil
110149}
150+
151+ func (filesystem * Filesystem ) GetDirEntriesNames (dir string ) ([]string , error ) {
152+ entries , err := os .ReadDir (dir )
153+ if err != nil {
154+ return nil , fmt .Errorf ("failed to read directory %s: %v" , dir , err )
155+ }
156+
157+ names := make ([]string , 0 , len (entries ))
158+
159+ for _ , entry := range entries {
160+ names = append (names , entry .Name ())
161+ }
162+
163+ return names , nil
164+ }
0 commit comments