diff --git a/Cargo.lock b/Cargo.lock index c70f2ce..ad67582 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1084,7 +1084,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "streamshare" -version = "4.0.0" +version = "4.1.0" dependencies = [ "futures", "reqwest", diff --git a/Cargo.toml b/Cargo.toml index cccd200..5e13f0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "streamshare" -version = "4.0.0" +version = "4.1.0" edition = "2021" description = "Upload to streamshare library" license = "MIT" diff --git a/README.md b/README.md index 9c44076..0c4f809 100644 --- a/README.md +++ b/README.md @@ -42,4 +42,15 @@ match client.delete(file_identifier, deletion_token).await { } ``` +Download: + +```rust +let client = StreamShare::default(); + +match client.download(file_identifier, path).await { + Ok(_) => println!("File downloaded successfully"), + Err(e) => eprintln!("Error downloaded 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 2240940..9604e76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,9 @@ use futures::{SinkExt, StreamExt}; use reqwest::Client; use serde::Deserialize; use std::path::Path; -use tokio::fs; use tokio::fs::File; use tokio::io::AsyncReadExt; +use tokio::{fs, io::AsyncWriteExt}; use tokio_tungstenite::{ connect_async, tungstenite::{self, Message}, @@ -127,6 +127,61 @@ impl StreamShare { Err(format!("Failed to delete file: {}", res.status()).into()) } } + + pub async fn download( + &self, + file_identifier: &str, + download_path: &str, + ) -> Result<(), Box> { + let res = self + .client + .get(format!( + "https://{}/download/{}", + self.server_url, file_identifier + )) + .send() + .await? + .error_for_status()?; + + let unknown = format!("{}.unknown", file_identifier); + + let file_name = res + .headers() + .get("content-disposition") + .and_then(|header| header.to_str().ok()) + .and_then(|header_value| { + header_value.split(';').find_map(|part| { + let trimmed = part.trim(); + if trimmed.starts_with("filename=") { + Some(trimmed.trim_start_matches("filename=").trim_matches('"')) + } else { + None + } + }) + }) + .unwrap_or(unknown.as_str()); + + let file_path = { + let path = Path::new(download_path); + if path.as_os_str().is_empty() { + Path::new("").join(file_name) + } else if path.is_dir() { + path.join(file_name) + } else { + path.to_path_buf() + } + }; + + if file_path.exists() { + return Err(format!("File already exists: {}", file_path.display()).into()); + } + + let mut file = File::create(file_path).await?; + let content = res.bytes().await?; + + file.write_all(&content).await?; + Ok(()) + } } impl Default for StreamShare {