@@ -33,14 +33,12 @@ func GetExt(fileName string) string {
3333// CheckNotExist check if the file exists
3434func CheckNotExist (src string ) bool {
3535 _ , err := os .Stat (src )
36-
3736 return os .IsNotExist (err )
3837}
3938
4039// CheckPermission check if the file has permission
4140func CheckPermission (src string ) bool {
4241 _ , err := os .Stat (src )
43-
4442 return os .IsPermission (err )
4543}
4644
@@ -51,11 +49,10 @@ func IsNotExistMkDir(src string) error {
5149 return err
5250 }
5351 }
54-
5552 return nil
5653}
5754
58- // MkDir create a directory ( safe permissions 0750 instead of os.ModePerm/0777)
55+ // MkDir create a directory with safe permissions 0750
5956func MkDir (src string ) error {
6057 err := os .MkdirAll (src , 0o750 )
6158 if err != nil {
@@ -96,7 +93,6 @@ func Open(name string, flag int, perm os.FileMode) (*os.File, error) {
9693 if err != nil {
9794 return nil , err
9895 }
99-
10096 return f , nil
10197}
10298
@@ -112,7 +108,6 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
112108 return nil , fmt .Errorf ("file.IsNotExistMkDir src: %s, err: %v" , src , err )
113109 }
114110
115- // owner-only read/write instead of overly permissive modes
116111 f , err := Open (src + fileName , os .O_APPEND | os .O_CREATE | os .O_RDWR , 0o600 )
117112 if err != nil {
118113 return nil , fmt .Errorf ("Fail to OpenFile :%v" , err )
@@ -161,12 +156,9 @@ func CreateFileAndWriteContent(path, content string) error {
161156 if err != nil {
162157 return err
163158 }
164-
165159 defer file .Close ()
166160 write := bufio .NewWriter (file )
167-
168161 write .WriteString (content )
169-
170162 write .Flush ()
171163 return nil
172164}
@@ -178,7 +170,6 @@ func IsNotExistCreateFile(src string) error {
178170 return err
179171 }
180172 }
181-
182173 return nil
183174}
184175
@@ -195,9 +186,7 @@ func ReadFullFile(path string) []byte {
195186 return content
196187}
197188
198- // copyFileContents holds the logic shared by CopyFile and CopySingleFile:
199- // remove an existing destination (unless style == "skip"), stream src -> dst,
200- // and mirror the source file's permissions (capped to a safe mask).
189+ // copyFileContents holds the logic shared by CopyFile and CopySingleFile
201190func copyFileContents (src , dst , style string ) error {
202191 if Exists (dst ) {
203192 if style == "skip" {
@@ -230,8 +219,7 @@ func copyFileContents(src, dst, style string) error {
230219 return os .Chmod (dst , srcinfo .Mode ()& 0o750 )
231220}
232221
233- // CopyFile copies a single file from src into the dst directory,
234- // keeping the source file's base name.
222+ // CopyFile copies a single file from src into the dst directory
235223func CopyFile (src , dst , style string ) error {
236224 lastPath := src [strings .LastIndex (src , "/" )+ 1 :]
237225
@@ -243,8 +231,7 @@ func CopyFile(src, dst, style string) error {
243231 return copyFileContents (src , dst , style )
244232}
245233
246- // CopySingleFile copies src to the exact dst path given (no directory
247- // join / renaming behavior).
234+ // CopySingleFile copies src to the exact dst path given
248235func CopySingleFile (src , dst , style string ) error {
249236 return copyFileContents (src , dst , style )
250237}
@@ -322,8 +309,6 @@ func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
322309 return err
323310 }
324311
325- // cap caller-supplied permissions to avoid accidentally creating
326- // world-writable files
327312 safePerm := perm & 0o750
328313
329314 file , err := os .OpenFile (fullPath ,
@@ -340,7 +325,7 @@ func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
340325}
341326
342327// SpliceFiles concatenates multiple file chunks into a single file
343- func SpliceFiles (dir , path string , length int , startPoint int ) error {
328+ func SpliceFiles (dir , path string , length , startPoint int ) error {
344329 fullPath := path
345330
346331 if err := IsNotExistCreateFile (fullPath ); err != nil {
@@ -486,7 +471,7 @@ func GetFileOrDirSize(path string) (int64, error) {
486471 return fileInfo .Size (), nil
487472}
488473
489- // DirSizeB calculates the total size of a directory in bytes
474+ // DirSizeB calculates total size of a directory in bytes
490475func DirSizeB (path string ) (int64 , error ) {
491476 var size int64
492477 err := filepath .Walk (path , func (_ string , info os.FileInfo , err error ) error {
@@ -557,146 +542,144 @@ func NameAccumulation(name, dir string) string {
557542 }
558543}
559544
560- func ParseFileHeader (h , boundary []byte ) (map [string ]string , bool ) {
561- arr := bytes .Split (h , boundary )
562- result := make (map [string ]string )
563- for _ , item := range arr {
564- tarr := bytes .Split (item , []byte (";" ))
565- if len (tarr ) != 2 {
566- continue
567- }
568-
569- tbyte := tarr [1 ]
570- tbyte = bytes .ReplaceAll (tbyte , []byte ("\r \n --" ), []byte ("" ))
571- tbyte = bytes .ReplaceAll (tbyte , []byte ("name=\" " ), []byte ("" ))
572- tempArr := bytes .Split (tbyte , []byte ("\" \r \n \r \n " ))
573- if len (tempArr ) != 2 {
574- continue
575- }
576- result [strings .TrimSpace (string (tempArr [0 ]))] = strings .TrimSpace (string (tempArr [1 ]))
545+ // parseHeaderFields extracts key-value pairs from header data
546+ func parseHeaderFields (item []byte ) (string , string , bool ) {
547+ tarr := bytes .Split (item , []byte (";" ))
548+ if len (tarr ) != 2 {
549+ return "" , "" , false
577550 }
578- return result , true
579- }
580-
581- func ReadToBoundary (boundary []byte , stream io.ReadCloser , target io.WriteCloser ) ([]byte , bool , error ) {
582- read_data := make ([]byte , 1024 * 8 )
583- read_data_len := 0
584- buf := make ([]byte , 1024 * 4 )
585- b_len := len (boundary )
586- reach_end := false
587- for ! reach_end {
588- read_len , err := stream .Read (buf )
589- if err != nil {
590- if err != io .EOF && read_len <= 0 {
591- return nil , true , err
592- }
593- reach_end = true
594- }
595551
596- copy (read_data [read_data_len :], buf [:read_len ])
597- read_data_len += read_len
598- if read_data_len < b_len + 4 {
599- continue
600- }
601- loc := bytes .Index (read_data [:read_data_len ], boundary )
602- if loc >= 0 {
603- target .Write (read_data [:loc - 4 ])
604- return read_data [loc :read_data_len ], reach_end , nil
605- }
606- target .Write (read_data [:read_data_len - b_len - 4 ])
607- copy (read_data [0 :], read_data [read_data_len - b_len - 4 :])
608- read_data_len = b_len + 4
552+ tbyte := tarr [1 ]
553+ tbyte = bytes .ReplaceAll (tbyte , []byte ("\r \n --" ), []byte ("" ))
554+ tbyte = bytes .ReplaceAll (tbyte , []byte ("name=\" " ), []byte ("" ))
555+ tempArr := bytes .Split (tbyte , []byte ("\" \r \n \r \n " ))
556+ if len (tempArr ) != 2 {
557+ return "" , "" , false
609558 }
610- target .Write (read_data [:read_data_len ])
611- return nil , reach_end , nil
559+ return strings .TrimSpace (string (tempArr [0 ])), strings .TrimSpace (string (tempArr [1 ])), true
612560}
613561
614- // parseFileHeaderFromData extracts file header map from raw data
615- func parseFileHeaderFromData ( data , boundary []byte ) (map [string ]string , bool ) {
616- arr := bytes .Split (data , boundary )
562+ // ParseFileHeader parses file header from raw data
563+ func ParseFileHeader ( h , boundary []byte ) (map [string ]string , bool ) {
564+ arr := bytes .Split (h , boundary )
617565 result := make (map [string ]string )
618566 for _ , item := range arr {
619- tarr := bytes . Split (item , [] byte ( ";" ) )
620- if len ( tarr ) != 2 {
621- continue
567+ key , value , ok := parseHeaderFields (item )
568+ if ok {
569+ result [ key ] = value
622570 }
623-
624- tbyte := tarr [1 ]
625- tbyte = bytes .ReplaceAll (tbyte , []byte ("\r \n --" ), []byte ("" ))
626- tbyte = bytes .ReplaceAll (tbyte , []byte ("name=\" " ), []byte ("" ))
627- tempArr := bytes .Split (tbyte , []byte ("\" \r \n \r \n " ))
628- if len (tempArr ) != 2 {
629- continue
630- }
631- result [strings .TrimSpace (string (tempArr [0 ]))] = strings .TrimSpace (string (tempArr [1 ]))
632571 }
633572 return result , true
634573}
635574
636- // findBoundaryInData locates the boundary in the data buffer
637- func findBoundaryInData (data []byte , boundary []byte , readTotal int ) int {
638- return bytes .LastIndex (data [:readTotal ], boundary )
575+ // readStreamChunk reads a chunk from the stream
576+ func readStreamChunk (stream io.ReadCloser , buf []byte ) (int , error ) {
577+ readLen , err := stream .Read (buf )
578+ if err != nil && err != io .EOF {
579+ return 0 , err
580+ }
581+ return readLen , nil
639582}
640583
641- // extractFileHeader extracts the file header from the read buffer
642- func extractFileHeader (data []byte , boundary []byte , readTotal int ) (map [string ]string , int , bool , error ) {
643- boundaryLoc := findBoundaryInData (data , boundary , readTotal )
644- if boundaryLoc == - 1 {
645- return nil , 0 , false , nil
646- }
584+ // locateBoundary finds the boundary in the data buffer
585+ func locateBoundary (data , boundary []byte , readTotal int ) int {
586+ return bytes .LastIndex (data [:readTotal ], boundary )
587+ }
647588
589+ // extractHeaderFromData extracts header map and remaining data
590+ func extractHeaderFromData (data , boundary []byte , readTotal , boundaryLoc int ) (map [string ]string , []byte , bool , error ) {
648591 startLoc := boundaryLoc + len (boundary )
649592 fileHeadLoc := bytes .Index (data [startLoc :readTotal ], []byte ("\r \n \r \n " ))
650593 if fileHeadLoc == - 1 {
651- return nil , 0 , false , nil
594+ return nil , nil , false , nil
652595 }
653596 fileHeadLoc += startLoc
654597
655- headMap , ok := parseFileHeaderFromData (data , boundary )
598+ headMap , ok := ParseFileHeader (data , boundary )
656599 if ! ok {
657- return headMap , 0 , false , fmt .Errorf ("ParseFileHeader fail: %s" , string (data [startLoc :fileHeadLoc ]))
600+ return headMap , nil , false , fmt .Errorf ("ParseFileHeader fail: %s" , string (data [startLoc :fileHeadLoc ]))
601+ }
602+ return headMap , data [fileHeadLoc + 4 : readTotal ], true , nil
603+ }
604+
605+ // ReadToBoundary reads data from stream until a boundary is found
606+ func ReadToBoundary (boundary []byte , stream io.ReadCloser , target io.WriteCloser ) ([]byte , bool , error ) {
607+ readData := make ([]byte , 1024 * 8 )
608+ readDataLen := 0
609+ buf := make ([]byte , 1024 * 4 )
610+ bLen := len (boundary )
611+ reachEnd := false
612+
613+ for ! reachEnd {
614+ readLen , err := readStreamChunk (stream , buf )
615+ if err != nil {
616+ return nil , true , err
617+ }
618+ if readLen <= 0 {
619+ reachEnd = true
620+ continue
621+ }
622+
623+ copy (readData [readDataLen :], buf [:readLen ])
624+ readDataLen += readLen
625+
626+ if readDataLen < bLen + 4 {
627+ continue
628+ }
629+
630+ loc := bytes .Index (readData [:readDataLen ], boundary )
631+ if loc >= 0 {
632+ target .Write (readData [:loc - 4 ])
633+ return readData [loc :readDataLen ], reachEnd , nil
634+ }
635+
636+ target .Write (readData [:readDataLen - bLen - 4 ])
637+ copy (readData [0 :], readData [readDataLen - bLen - 4 :])
638+ readDataLen = bLen + 4
658639 }
659- return headMap , fileHeadLoc + 4 , true , nil
640+
641+ target .Write (readData [:readDataLen ])
642+ return nil , reachEnd , nil
660643}
661644
662645// ParseFromHead parses the file header from the beginning of the stream
663- func ParseFromHead (read_data []byte , read_total int , boundary []byte , stream io.ReadCloser ) (map [string ]string , []byte , error ) {
646+ func ParseFromHead (readData []byte , readTotal int , boundary []byte , stream io.ReadCloser ) (map [string ]string , []byte , error ) {
664647 buf := make ([]byte , 1024 * 8 )
665648 foundBoundary := false
666649 boundaryLoc := - 1
667650
668651 for {
669- readLen , err := stream . Read ( buf )
670- if err != nil && err != io . EOF {
652+ readLen , err := readStreamChunk ( stream , buf )
653+ if err != nil {
671654 return nil , nil , err
672655 }
673656 if readLen <= 0 {
674657 break
675658 }
676659
677- if read_total + readLen > cap (read_data ) {
660+ if readTotal + readLen > cap (readData ) {
678661 return nil , nil , fmt .Errorf ("not found boundary" )
679662 }
680663
681- copy (read_data [ read_total :], buf [:readLen ])
682- read_total += readLen
664+ copy (readData [ readTotal :], buf [:readLen ])
665+ readTotal += readLen
683666
684667 if ! foundBoundary {
685- boundaryLoc = findBoundaryInData ( read_data , boundary , read_total )
668+ boundaryLoc = locateBoundary ( readData , boundary , readTotal )
686669 if boundaryLoc == - 1 {
687670 continue
688671 }
689672 foundBoundary = true
690673 }
691674
692- headMap , endLoc , ok , err := extractFileHeader ( read_data , boundary , read_total )
675+ headMap , remainingData , ok , err := extractHeaderFromData ( readData , boundary , readTotal , boundaryLoc )
693676 if err != nil {
694677 return nil , nil , err
695678 }
696- if ! ok {
697- continue
679+ if ok {
680+ return headMap , remainingData , nil
698681 }
699- return headMap , read_data [endLoc :read_total ], nil
700682 }
683+
701684 return nil , nil , fmt .Errorf ("reach to stream EOF" )
702685}
0 commit comments