@@ -97,8 +97,8 @@ func (h *HTTPDownloader) fetchProxyFromEnv(scheme string) {
97
97
}
98
98
}
99
99
100
- // DownloadFile download a file with the progress
101
- func (h * HTTPDownloader ) DownloadFile () error {
100
+ // DownloadAsStream downloads the file as stream
101
+ func (h * HTTPDownloader ) DownloadAsStream ( writer io. Writer ) ( err error ) {
102
102
filepath , downloadURL , showProgress := h .TargetFilePath , h .URL , h .ShowProgress
103
103
// Get the data
104
104
if h .Context == nil {
@@ -115,7 +115,10 @@ func (h *HTTPDownloader) DownloadFile() error {
115
115
116
116
if h .UserName != "" && h .Password != "" {
117
117
req .SetBasicAuth (h .UserName , h .Password )
118
+ } else if h .Password != "" {
119
+ req .Header .Set ("Authorization" , "Bearer " + h .Password )
118
120
}
121
+
119
122
var tr http.RoundTripper
120
123
if h .RoundTripper != nil {
121
124
tr = h .RoundTripper
@@ -178,22 +181,32 @@ func (h *HTTPDownloader) DownloadFile() error {
178
181
}
179
182
}
180
183
181
- if err := os .MkdirAll (path .Dir (filepath ), os .FileMode (0755 )); err != nil {
182
- return err
184
+ h .progressIndicator .Writer = writer
185
+ h .progressIndicator .Init ()
186
+
187
+ // Write the body to file
188
+ _ , err = io .Copy (h .progressIndicator , resp .Body )
189
+ return
190
+ }
191
+
192
+ // DownloadFile download a file with the progress
193
+ func (h * HTTPDownloader ) DownloadFile () (err error ) {
194
+ filepath := h .TargetFilePath
195
+ if err = os .MkdirAll (path .Dir (filepath ), os .FileMode (0755 )); err != nil {
196
+ return
183
197
}
184
198
185
199
// Create the file
186
- out , err := os .Create (filepath )
200
+ var out io.WriteCloser
201
+ out , err = os .Create (filepath )
187
202
if err != nil {
188
- _ = out .Close ()
189
- return err
203
+ return
190
204
}
205
+ defer func () {
206
+ _ = out .Close ()
207
+ }()
191
208
192
- h .progressIndicator .Writer = out
193
- h .progressIndicator .Init ()
194
-
195
- // Write the body to file
196
- _ , err = io .Copy (h .progressIndicator , resp .Body )
209
+ err = h .DownloadAsStream (out )
197
210
return err
198
211
}
199
212
@@ -269,6 +282,39 @@ func (c *ContinueDownloader) WithBasicAuth(username, password string) *ContinueD
269
282
return c
270
283
}
271
284
285
+ // DownloadWithContinueAsStream downloads the files continuously
286
+ func (c * ContinueDownloader ) DownloadWithContinueAsStream (targetURL string , output io.Writer , index , continueAt , end int64 , showProgress bool ) (err error ) {
287
+ c .downloader = & HTTPDownloader {
288
+ URL : targetURL ,
289
+ ShowProgress : showProgress ,
290
+ NoProxy : c .noProxy ,
291
+ RoundTripper : c .roundTripper ,
292
+ InsecureSkipVerify : c .insecureSkipVerify ,
293
+ UserName : c .UserName ,
294
+ Password : c .Password ,
295
+ Context : c .Context ,
296
+ Timeout : c .Timeout ,
297
+ }
298
+ if index >= 0 {
299
+ c .downloader .Title = fmt .Sprintf ("Downloading part %d" , index )
300
+ }
301
+
302
+ if continueAt >= 0 {
303
+ c .downloader .Header = make (map [string ]string , 1 )
304
+
305
+ if end > continueAt {
306
+ c .downloader .Header ["Range" ] = fmt .Sprintf ("bytes=%d-%d" , continueAt , end )
307
+ } else {
308
+ c .downloader .Header ["Range" ] = fmt .Sprintf ("bytes=%d-" , continueAt )
309
+ }
310
+ }
311
+
312
+ if err = c .downloader .DownloadAsStream (output ); err != nil {
313
+ err = fmt .Errorf ("cannot download from %s, error: %v" , targetURL , err )
314
+ }
315
+ return
316
+ }
317
+
272
318
// DownloadWithContinue downloads the files continuously
273
319
func (c * ContinueDownloader ) DownloadWithContinue (targetURL , output string , index , continueAt , end int64 , showProgress bool ) (err error ) {
274
320
c .downloader = & HTTPDownloader {
@@ -303,6 +349,45 @@ func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, inde
303
349
return
304
350
}
305
351
352
+ // DetectSizeWithRoundTripperAndAuthStream returns the size of target resource
353
+ func DetectSizeWithRoundTripperAndAuthStream (targetURL string , output io.Writer , showProgress , noProxy , insecureSkipVerify bool ,
354
+ roundTripper http.RoundTripper , username , password string , timeout time.Duration ) (total int64 , rangeSupport bool , err error ) {
355
+ downloader := HTTPDownloader {
356
+ URL : targetURL ,
357
+ ShowProgress : showProgress ,
358
+ RoundTripper : roundTripper ,
359
+ NoProxy : false , // below HTTP request does not need proxy
360
+ InsecureSkipVerify : insecureSkipVerify ,
361
+ UserName : username ,
362
+ Password : password ,
363
+ Timeout : timeout ,
364
+ }
365
+
366
+ var detectOffset int64
367
+ var lenErr error
368
+
369
+ detectOffset = 2
370
+ downloader .Header = make (map [string ]string , 1 )
371
+ downloader .Header ["Range" ] = fmt .Sprintf ("bytes=%d-" , detectOffset )
372
+
373
+ downloader .PreStart = func (resp * http.Response ) bool {
374
+ rangeSupport = resp .StatusCode == http .StatusPartialContent
375
+ contentLen := resp .Header .Get ("Content-Length" )
376
+ if total , lenErr = strconv .ParseInt (contentLen , 10 , 0 ); lenErr == nil {
377
+ total += detectOffset
378
+ } else {
379
+ rangeSupport = false
380
+ }
381
+ // always return false because we just want to get the header from response
382
+ return false
383
+ }
384
+
385
+ if err = downloader .DownloadAsStream (output ); err != nil || lenErr != nil {
386
+ err = fmt .Errorf ("cannot download from %s, response error: %v, content length error: %v" , targetURL , err , lenErr )
387
+ }
388
+ return
389
+ }
390
+
306
391
// DetectSizeWithRoundTripperAndAuth returns the size of target resource
307
392
func DetectSizeWithRoundTripperAndAuth (targetURL , output string , showProgress , noProxy , insecureSkipVerify bool ,
308
393
roundTripper http.RoundTripper , username , password string , timeout time.Duration ) (total int64 , rangeSupport bool , err error ) {
0 commit comments