11package strm
22
33import (
4+ "bytes"
45 "context"
6+ "crypto/sha256"
57 "errors"
8+ "io"
69 "os"
710 stdpath "path"
811 "strings"
@@ -90,6 +93,9 @@ func RemoveStrm(dstPath string, d *Strm) {
9093
9194func generateStrm (ctx context.Context , driver * Strm , obj model.Obj , localPath string ) {
9295 if ! obj .IsDir () {
96+ if utils .Exists (localPath ) && driver .SaveLocalMode == SaveLocalInsertMode {
97+ return
98+ }
9399 link , err := driver .Link (ctx , obj , model.LinkArgs {})
94100 if err != nil {
95101 log .Warnf ("failed to generate strm of obj %s: failed to link: %v" , localPath , err )
@@ -111,6 +117,20 @@ func generateStrm(ctx context.Context, driver *Strm, obj model.Obj, localPath st
111117 return
112118 }
113119 defer rc .Close ()
120+ same , err := isSameContent (localPath , size , rc )
121+ if err != nil {
122+ log .Warnf ("failed to compare content of obj %s: %v" , localPath , err )
123+ return
124+ }
125+ if same {
126+ return
127+ }
128+ rc , err = rrf .RangeRead (ctx , http_range.Range {Length : - 1 })
129+ if err != nil {
130+ log .Warnf ("failed to generate strm of obj %s: failed to reread range: %v" , localPath , err )
131+ return
132+ }
133+ defer rc .Close ()
114134 file , err := utils .CreateNestedFile (localPath )
115135 if err != nil {
116136 log .Warnf ("failed to generate strm of obj %s: failed to create local file: %v" , localPath , err )
@@ -123,7 +143,38 @@ func generateStrm(ctx context.Context, driver *Strm, obj model.Obj, localPath st
123143 }
124144}
125145
146+ func isSameContent (localPath string , size int64 , rc io.Reader ) (bool , error ) {
147+ info , err := os .Stat (localPath )
148+ if err != nil {
149+ if os .IsNotExist (err ) {
150+ return false , nil
151+ }
152+ return false , err
153+ }
154+
155+ if info .Size () != size {
156+ return false , nil
157+ }
158+ localFile , err := os .Open (localPath )
159+ if err != nil {
160+ return false , err
161+ }
162+ defer localFile .Close ()
163+ h1 := sha256 .New ()
164+ h2 := sha256 .New ()
165+ if _ , err := io .Copy (h1 , localFile ); err != nil {
166+ return false , err
167+ }
168+ if _ , err := io .Copy (h2 , rc ); err != nil {
169+ return false , err
170+ }
171+ return bytes .Equal (h1 .Sum (nil ), h2 .Sum (nil )), nil
172+ }
173+
126174func deleteExtraFiles (driver * Strm , localPath string , objs []model.Obj ) {
175+ if driver .SaveLocalMode != SaveLocalSyncMode {
176+ return
177+ }
127178 localFiles , err := getLocalFiles (localPath )
128179 if err != nil {
129180 log .Errorf ("Failed to read local files from %s: %v" , localPath , err )
@@ -145,15 +196,6 @@ func deleteExtraFiles(driver *Strm, localPath string, objs []model.Obj) {
145196
146197 for _ , localFile := range localFiles {
147198 if _ , exists := objsSet [localFile ]; ! exists {
148- ext := utils .Ext (localFile )
149- localFileName := stdpath .Base (localFile )
150- localFileBaseName := strings .TrimSuffix (localFile , utils .SourceExt (localFileName ))
151- _ , nameExists := objsBaseNameSet [localFileBaseName [:len (localFileBaseName )- 1 ]]
152- _ , downloadFile := driver .downloadSuffix [ext ]
153- if driver .KeepLocalDownloadFile && nameExists && downloadFile {
154- continue
155- }
156-
157199 err := os .Remove (localFile )
158200 if err != nil {
159201 log .Errorf ("Failed to delete file: %s, error: %v\n " , localFile , err )
0 commit comments