From 56207bebd7745bf0f136376e1670a6e96c8e4297 Mon Sep 17 00:00:00 2001 From: Waradu Date: Sun, 20 Oct 2024 13:02:04 +0200 Subject: [PATCH] custom progress callback --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 15 +++++++++++++-- src/lib.rs | 49 +++++++------------------------------------------ 4 files changed, 22 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29ab4a4..ad25017 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1084,7 +1084,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "streamshare" -version = "2.0.0" +version = "3.0.0" dependencies = [ "futures", "reqwest", diff --git a/Cargo.toml b/Cargo.toml index cf3e3d3..c3de68f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "streamshare" -version = "2.0.0" +version = "3.0.0" edition = "2021" description = "Upload to streamshare library" license = "MIT" diff --git a/README.md b/README.md index da47d3e..311afba 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,17 @@ Upload files to [streamshare](https://streamshare.wireway.ch) #### Example: Upload: + ```rust -let show_progress = true; -match upload(&file_path, show_progress).await { +let callback = |uploaded_bytes, total_bytes| { + println!( + "Uploaded {}b of {}b", + uploaded_bytes, + total_bytes + ); +} + +match upload(&file_path, callback).await { Ok((file_identifier, _deletion_token)) => { let download_url = format!( "https://streamshare.wireway.ch/download/{}", @@ -22,9 +30,12 @@ match upload(&file_path, show_progress).await { ``` Delete: + ```rust match streamshare::delete(file_identifier, deletion_token).await { Ok(_) => println!("File deleted successfully"), Err(e) => eprintln!("Error deleting file: {}", e), } ``` + +Check [toss](https://github.com/Waradu/to-streamshare) for a better example on how to use it. diff --git a/src/lib.rs b/src/lib.rs index 19b17c2..eb0746f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use futures::{SinkExt, StreamExt}; use reqwest::Client; use serde::Deserialize; -use std::{io::Write, path::Path, time::Instant}; +use std::path::Path; use tokio::fs; use tokio::fs::File; use tokio::io::AsyncReadExt; @@ -17,7 +17,10 @@ struct CreateResponse { deletion_token: String, } -pub async fn upload(file_path: &str, show_progress: bool) -> Result<(String, String), Box> { +pub async fn upload(file_path: &str, mut callback: F) -> Result<(String, String), Box> +where + F: FnMut(u64, u64) +{ let path = Path::new(file_path); let metadata = fs::metadata(path).await?; if !metadata.is_file() { @@ -51,10 +54,9 @@ pub async fn upload(file_path: &str, show_progress: bool) -> Result<(String, Str let (mut ws_stream, _) = connect_async(ws_url).await?; let mut file = File::open(path).await?; - const CHUNK_SIZE: usize = 512 * 1024; + const CHUNK_SIZE: usize = 1024 * 1024; let mut buffer = vec![0u8; CHUNK_SIZE]; let mut uploaded: u64 = 0; - let start_time = Instant::now(); loop { let n = file.read(&mut buffer).await?; @@ -67,19 +69,7 @@ pub async fn upload(file_path: &str, show_progress: bool) -> Result<(String, Str ws_stream.send(Message::Binary(chunk.to_vec())).await?; uploaded += n as u64; - if show_progress { - let percentage = (uploaded as f64 / file_size as f64) * 100.0; - let uploaded_mb = bytes_to_human_readable(uploaded); - let total_mb = bytes_to_human_readable(file_size); - let elapsed_secs = start_time.elapsed().as_secs_f64(); - let speed = bytes_to_human_readable((uploaded as f64 / elapsed_secs) as u64); - - print!( - "\r\x1b[2K{:.2}% {}/{} ({}/s)", - percentage, uploaded_mb, total_mb, speed - ); - std::io::stdout().flush().unwrap(); - } + callback(uploaded, file_size); match ws_stream.next().await { Some(Ok(Message::Text(text))) if text == "ACK" => (), @@ -91,15 +81,6 @@ pub async fn upload(file_path: &str, show_progress: bool) -> Result<(String, Str } } - if show_progress { - println!( - "\r\x1b[2K100.00% {}/{} (Upload complete)", - bytes_to_human_readable(file_size), - bytes_to_human_readable(file_size) - ); - println!(); - } - ws_stream .close(Some(tungstenite::protocol::CloseFrame { code: tungstenite::protocol::frame::coding::CloseCode::Normal, @@ -130,19 +111,3 @@ pub async fn delete( Err(format!("Failed to delete file: {}", res.status()).into()) } } - -fn bytes_to_human_readable(bytes: u64) -> String { - const KB: f64 = 1024.0; - const MB: f64 = KB * 1024.0; - const GB: f64 = MB * 1024.0; - - if bytes as f64 >= GB { - format!("{:.2}gb", bytes as f64 / GB) - } else if bytes as f64 >= MB { - format!("{:.2}mb", bytes as f64 / MB) - } else if bytes as f64 >= KB { - format!("{:.2}kb", bytes as f64 / KB) - } else { - format!("{}b", bytes) - } -}