Created
February 19, 2024 18:28
-
-
Save cs50victor/f7b0d8cc5d59da8ac8ef2d863f5b9d18 to your computer and use it in GitHub Desktop.
Download a file with progress feedback using rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [package] | |
| name = "example" | |
| version = "0.1.0" | |
| edition = "2021" | |
| [dependencies] | |
| reqwest = { version = "0.11.3", features = ["stream"] } | |
| futures-util = "0.3.14" | |
| tokio = { version = "1.13.0", features = ["full"] } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use futures_util::StreamExt; | |
| use std::io::{Seek, Write}; | |
| use reqwest::Client; | |
| use std::cmp::min; | |
| use std::fs::File; | |
| pub async fn download_file<'a>(client: &Client, url: &str, path: &'a str) -> Result<&'a str, String> { | |
| let mut downloaded = 0_u64; | |
| let mut file = match std::path::Path::new(path).exists() { | |
| true => { | |
| println!("File exists. Resuming."); | |
| let mut file = std::fs::OpenOptions::new() | |
| .read(true) | |
| .append(true) | |
| .open(path) | |
| .unwrap(); | |
| let file_size = std::fs::metadata(path).unwrap().len(); | |
| file.seek(std::io::SeekFrom::Start(file_size)).unwrap(); | |
| downloaded = file_size; | |
| file | |
| }, | |
| false => { | |
| println!("Fresh file.."); | |
| File::create(path).or(Err(format!("Failed to create file '{}'", path)))? | |
| }, | |
| }; | |
| let res = client | |
| .get(url) | |
| .send() | |
| .await | |
| .or(Err(format!("Failed to GET from '{}'", &url)))?; | |
| let total_size = res | |
| .content_length() | |
| .ok_or(format!("Failed to get content length from '{}'", &url))?; | |
| if downloaded >= total_size { | |
| println!("File already completed downloaded."); | |
| return Ok(path) | |
| }; | |
| let mut stream = res.bytes_stream(); | |
| while let Some(item) = stream.next().await { | |
| let chunk = item.or(Err("Error while downloading file".to_string()))?; | |
| file.write_all(&chunk) | |
| .or(Err("Error while writing to file".to_string()))?; | |
| downloaded = min(downloaded + (chunk.len() as u64), total_size); | |
| println!( | |
| "downloaded {:.2}%", | |
| (downloaded as f64 / total_size as f64) * 100.0 | |
| ); | |
| } | |
| Ok(path) | |
| } | |
| #[tokio::main] | |
| async fn main() { | |
| let url = "https://huggingface.co/datasets/cs50victor/splats/resolve/main/train/point_cloud/iteration_7000/point_cloud.gcloud"; | |
| let path = download_file( | |
| &Client::new(), | |
| url, | |
| "point_cloud.gcloud", | |
| ) | |
| .await | |
| .unwrap(); | |
| println!("{}",&format!("Downloaded {} to {}", url, path)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment