@@ -541,19 +541,22 @@ type downloader struct {
541
541
in * DownloadObjectInput
542
542
out * DownloadObjectOutput
543
543
544
- wg sync.WaitGroup
545
- m sync.Mutex
544
+ wg sync.WaitGroup
545
+ m sync.Mutex
546
+ etagOnce sync.Once
547
+ totalBytesOnce sync.Once
546
548
547
549
offset int64
548
550
pos int64
549
551
totalBytes int64
550
552
written int64
553
+ etag string
551
554
552
555
err error
553
556
}
554
557
555
558
func (d * downloader ) download (ctx context.Context ) (* DownloadObjectOutput , error ) {
556
- if err := d .init (ctx ); err != nil {
559
+ if err := d .init (); err != nil {
557
560
return nil , fmt .Errorf ("unable to initialize download: %w" , err )
558
561
}
559
562
@@ -600,12 +603,12 @@ func (d *downloader) download(ctx context.Context) (*DownloadObjectOutput, error
600
603
d .wg .Wait ()
601
604
}
602
605
} else {
603
- if d .in .Range == "" {
604
- output = d .getChunk (ctx , 0 , d .byteRange (), clientOptions ... )
605
- } else {
606
+ if d .in .Range != "" {
606
607
d .pos , d .totalBytes = d .getDownloadRange ()
607
608
d .offset = d .pos
608
609
}
610
+
611
+ d .getChunk (ctx , 0 , d .byteRange (), clientOptions ... )
609
612
total := d .totalBytes
610
613
611
614
ch := make (chan dlChunk , d .options .Concurrency )
@@ -639,7 +642,7 @@ func (d *downloader) download(ctx context.Context) (*DownloadObjectOutput, error
639
642
return d .out , nil
640
643
}
641
644
642
- func (d * downloader ) init (ctx context. Context ) error {
645
+ func (d * downloader ) init () error {
643
646
if d .options .PartSizeBytes < minPartSizeBytes {
644
647
return fmt .Errorf ("part size must be at least %d bytes" , minPartSizeBytes )
645
648
}
@@ -655,7 +658,6 @@ func (d *downloader) init(ctx context.Context) error {
655
658
656
659
func (d * downloader ) singleDownload (ctx context.Context , clientOptions ... func (* s3.Options )) (* DownloadObjectOutput , error ) {
657
660
chunk := dlChunk {w : d .in .WriterAt }
658
- // d.in.PartNumber = 0
659
661
output , err := d .downloadChunk (ctx , chunk , clientOptions ... )
660
662
if err != nil {
661
663
return nil , err
@@ -708,6 +710,9 @@ func (d *downloader) downloadChunk(ctx context.Context, chunk dlChunk, clientOpt
708
710
if chunk .withRange != "" {
709
711
params .Range = aws .String (chunk .withRange )
710
712
}
713
+ if params .VersionId == nil && d .etag != "" {
714
+ params .IfMatch = aws .String (d .etag )
715
+ }
711
716
712
717
var out * s3.GetObjectOutput
713
718
var n int64
@@ -737,6 +742,9 @@ func (d *downloader) downloadChunk(ctx context.Context, chunk dlChunk, clientOpt
737
742
if out != nil {
738
743
output = & DownloadObjectOutput {}
739
744
output .mapFromGetObjectOutput (out , params .ChecksumMode )
745
+ d .etagOnce .Do (func () {
746
+ d .etag = aws .ToString (out .ETag )
747
+ })
740
748
}
741
749
return output , err
742
750
}
@@ -747,7 +755,9 @@ func (d *downloader) tryDownloadChunk(ctx context.Context, params *s3.GetObjectI
747
755
return nil , 0 , err
748
756
}
749
757
750
- d .setTotalBytes (out ) // Set total if not yet set.
758
+ d .totalBytesOnce .Do (func () {
759
+ d .setTotalBytes (out )
760
+ }) // Set total in first GET
751
761
752
762
var n int64
753
763
defer out .Body .Close ()
@@ -780,9 +790,6 @@ func (d *downloader) getTotalBytes() int64 {
780
790
// does not include a Content-Range. Meaning the object was not chunked. This
781
791
// occurs when the full file fits within the PartSize directive.
782
792
func (d * downloader ) setTotalBytes (resp * s3.GetObjectOutput ) {
783
- d .m .Lock ()
784
- defer d .m .Unlock ()
785
-
786
793
if d .totalBytes >= 0 {
787
794
return
788
795
}
0 commit comments