@@ -97,8 +97,7 @@ func (h *HTTPDownloader) fetchProxyFromEnv(scheme string) {
9797 }
9898}
9999
100- // DownloadFile download a file with the progress
101- func (h * HTTPDownloader ) DownloadFile () error {
100+ func (h * HTTPDownloader ) DownloadAsStream (writer io.Writer ) (err error ) {
102101 filepath , downloadURL , showProgress := h .TargetFilePath , h .URL , h .ShowProgress
103102 // Get the data
104103 if h .Context == nil {
@@ -181,22 +180,32 @@ func (h *HTTPDownloader) DownloadFile() error {
181180 }
182181 }
183182
184- if err := os .MkdirAll (path .Dir (filepath ), os .FileMode (0755 )); err != nil {
185- return err
183+ h .progressIndicator .Writer = writer
184+ h .progressIndicator .Init ()
185+
186+ // Write the body to file
187+ _ , err = io .Copy (h .progressIndicator , resp .Body )
188+ return
189+ }
190+
191+ // DownloadFile download a file with the progress
192+ func (h * HTTPDownloader ) DownloadFile () (err error ) {
193+ filepath := h .TargetFilePath
194+ if err = os .MkdirAll (path .Dir (filepath ), os .FileMode (0755 )); err != nil {
195+ return
186196 }
187197
188198 // Create the file
189- out , err := os .Create (filepath )
199+ var out io.WriteCloser
200+ out , err = os .Create (filepath )
190201 if err != nil {
191- _ = out .Close ()
192- return err
202+ return
193203 }
204+ defer func () {
205+ _ = out .Close ()
206+ }()
194207
195- h .progressIndicator .Writer = out
196- h .progressIndicator .Init ()
197-
198- // Write the body to file
199- _ , err = io .Copy (h .progressIndicator , resp .Body )
208+ err = h .DownloadAsStream (out )
200209 return err
201210}
202211
@@ -272,6 +281,38 @@ func (c *ContinueDownloader) WithBasicAuth(username, password string) *ContinueD
272281 return c
273282}
274283
284+ func (c * ContinueDownloader ) DownloadWithContinueAsStream (targetURL string , output io.Writer , index , continueAt , end int64 , showProgress bool ) (err error ) {
285+ c .downloader = & HTTPDownloader {
286+ URL : targetURL ,
287+ ShowProgress : showProgress ,
288+ NoProxy : c .noProxy ,
289+ RoundTripper : c .roundTripper ,
290+ InsecureSkipVerify : c .insecureSkipVerify ,
291+ UserName : c .UserName ,
292+ Password : c .Password ,
293+ Context : c .Context ,
294+ Timeout : c .Timeout ,
295+ }
296+ if index >= 0 {
297+ c .downloader .Title = fmt .Sprintf ("Downloading part %d" , index )
298+ }
299+
300+ if continueAt >= 0 {
301+ c .downloader .Header = make (map [string ]string , 1 )
302+
303+ if end > continueAt {
304+ c .downloader .Header ["Range" ] = fmt .Sprintf ("bytes=%d-%d" , continueAt , end )
305+ } else {
306+ c .downloader .Header ["Range" ] = fmt .Sprintf ("bytes=%d-" , continueAt )
307+ }
308+ }
309+
310+ if err = c .downloader .DownloadAsStream (output ); err != nil {
311+ err = fmt .Errorf ("cannot download from %s, error: %v" , targetURL , err )
312+ }
313+ return
314+ }
315+
275316// DownloadWithContinue downloads the files continuously
276317func (c * ContinueDownloader ) DownloadWithContinue (targetURL , output string , index , continueAt , end int64 , showProgress bool ) (err error ) {
277318 c .downloader = & HTTPDownloader {
@@ -306,6 +347,44 @@ func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, inde
306347 return
307348}
308349
350+ func DetectSizeWithRoundTripperAndAuthStream (targetURL string , output io.Writer , showProgress , noProxy , insecureSkipVerify bool ,
351+ roundTripper http.RoundTripper , username , password string , timeout time.Duration ) (total int64 , rangeSupport bool , err error ) {
352+ downloader := HTTPDownloader {
353+ URL : targetURL ,
354+ ShowProgress : showProgress ,
355+ RoundTripper : roundTripper ,
356+ NoProxy : false , // below HTTP request does not need proxy
357+ InsecureSkipVerify : insecureSkipVerify ,
358+ UserName : username ,
359+ Password : password ,
360+ Timeout : timeout ,
361+ }
362+
363+ var detectOffset int64
364+ var lenErr error
365+
366+ detectOffset = 2
367+ downloader .Header = make (map [string ]string , 1 )
368+ downloader .Header ["Range" ] = fmt .Sprintf ("bytes=%d-" , detectOffset )
369+
370+ downloader .PreStart = func (resp * http.Response ) bool {
371+ rangeSupport = resp .StatusCode == http .StatusPartialContent
372+ contentLen := resp .Header .Get ("Content-Length" )
373+ if total , lenErr = strconv .ParseInt (contentLen , 10 , 0 ); lenErr == nil {
374+ total += detectOffset
375+ } else {
376+ rangeSupport = false
377+ }
378+ // always return false because we just want to get the header from response
379+ return false
380+ }
381+
382+ if err = downloader .DownloadAsStream (output ); err != nil || lenErr != nil {
383+ err = fmt .Errorf ("cannot download from %s, response error: %v, content length error: %v" , targetURL , err , lenErr )
384+ }
385+ return
386+ }
387+
309388// DetectSizeWithRoundTripperAndAuth returns the size of target resource
310389func DetectSizeWithRoundTripperAndAuth (targetURL , output string , showProgress , noProxy , insecureSkipVerify bool ,
311390 roundTripper http.RoundTripper , username , password string , timeout time.Duration ) (total int64 , rangeSupport bool , err error ) {
0 commit comments