@@ -28,7 +28,7 @@ use std::fs;
2828use std:: env;
2929use std:: io:: Read ;
3030// use tokio::fs::File; // Unused import
31- use tokio:: io:: AsyncWriteExt ;
31+ use tokio:: io:: { AsyncWriteExt , BufWriter } ;
3232
3333/// Base URL for downloading images
3434const IMAGE_URL_BASE : & str = "https://github.com/arceos-hypervisor/axvisor-guest/releases/download/v0.0.18/" ;
@@ -345,21 +345,46 @@ async fn image_download(image_name: &str, output_dir: Option<String>, extract: b
345345 println ! ( "Starting download..." ) ;
346346
347347 // Use reqwest to download the file
348- let response = reqwest:: get ( & download_url) . await ?;
348+ let mut response = reqwest:: get ( & download_url) . await ?;
349349 if !response. status ( ) . is_success ( ) {
350350 return Err ( anyhow ! ( "Failed to download file: HTTP {}" , response. status( ) ) ) ;
351351 }
352352
353- let bytes = response. bytes ( ) . await ?;
354-
355- // Write all bytes at once, ensuring we overwrite any existing file
356- let mut file = tokio:: fs:: OpenOptions :: new ( )
353+ // Create file with buffered writer for efficient streaming
354+ let file = tokio:: fs:: OpenOptions :: new ( )
357355 . write ( true )
358356 . create ( true )
359357 . truncate ( true )
360358 . open ( & output_path)
361359 . await ?;
362- file. write_all ( & bytes) . await ?;
360+ let mut writer = BufWriter :: new ( file) ;
361+
362+ // Get content length for progress reporting (if available)
363+ let content_length = response. content_length ( ) ;
364+ let mut downloaded = 0u64 ;
365+
366+ // Stream the response body to file using chunks
367+ while let Some ( chunk) = response. chunk ( ) . await ? {
368+ // Write chunk to file
369+ writer. write_all ( & chunk) . await
370+ . map_err ( |e| anyhow ! ( "Error writing to file: {}" , e) ) ?;
371+
372+ // Update progress
373+ downloaded += chunk. len ( ) as u64 ;
374+ if let Some ( total) = content_length {
375+ let percent = ( downloaded * 100 ) / total;
376+ print ! ( "\r Downloading: {}% ({}/{} bytes)" , percent, downloaded, total) ;
377+ } else {
378+ print ! ( "\r Downloaded: {} bytes" , downloaded) ;
379+ }
380+ std:: io:: Write :: flush ( & mut std:: io:: stdout ( ) ) . unwrap ( ) ;
381+ }
382+
383+ // Flush the writer to ensure all data is written to disk
384+ writer. flush ( ) . await
385+ . map_err ( |e| anyhow ! ( "Error flushing file: {}" , e) ) ?;
386+
387+ println ! ( "\n Download completed" ) ;
363388
364389
365390 // Verify downloaded file
0 commit comments