@@ -97,8 +97,8 @@ func (h *HTTPDownloader) fetchProxyFromEnv(scheme string) {
9797}
9898}
9999
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 ) {
102102filepath , downloadURL , showProgress := h .TargetFilePath , h .URL , h .ShowProgress
103103// Get the data
104104if h .Context == nil {
@@ -115,7 +115,10 @@ func (h *HTTPDownloader) DownloadFile() error {
115115
116116if h .UserName != "" && h .Password != "" {
117117req .SetBasicAuth (h .UserName , h .Password )
118+ } else if h .Password != "" {
119+ req .Header .Set ("Authorization" , "Bearer " + h .Password )
118120}
121+
119122var tr http.RoundTripper
120123if h .RoundTripper != nil {
121124tr = h .RoundTripper
@@ -178,22 +181,32 @@ func (h *HTTPDownloader) DownloadFile() error {
178181}
179182}
180183
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
183197}
184198
185199// Create the file
186- out , err := os .Create (filepath )
200+ var out io.WriteCloser
201+ out , err = os .Create (filepath )
187202if err != nil {
188- _ = out .Close ()
189- return err
203+ return
190204}
205+ defer func () {
206+ _ = out .Close ()
207+ }()
191208
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 )
197210return err
198211}
199212
@@ -269,6 +282,39 @@ func (c *ContinueDownloader) WithBasicAuth(username, password string) *ContinueD
269282return c
270283}
271284
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+
272318// DownloadWithContinue downloads the files continuously
273319func (c * ContinueDownloader ) DownloadWithContinue (targetURL , output string , index , continueAt , end int64 , showProgress bool ) (err error ) {
274320c .downloader = & HTTPDownloader {
@@ -303,6 +349,45 @@ func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, inde
303349return
304350}
305351
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+
306391// DetectSizeWithRoundTripperAndAuth returns the size of target resource
307392func DetectSizeWithRoundTripperAndAuth (targetURL , output string , showProgress , noProxy , insecureSkipVerify bool ,
308393roundTripper http.RoundTripper , username , password string , timeout time.Duration ) (total int64 , rangeSupport bool , err error ) {
0 commit comments