Skip to main content

download/
download.rs

1/// Download module test example
2///
3/// This example demonstrates the download functionality including:
4/// - Getting file info to obtain fs_id
5/// - Single-threaded download with timing
6/// - Producer-consumer parallel download (queue-based)
7/// - Auto download mode (automatic selection based on file size)
8/// - Download speed comparison
9use baidu_netdisk_sdk::BaiduNetDiskClient;
10use log::info;
11use std::io::{self, BufRead};
12use std::time::{Duration, Instant};
13
14#[tokio::main]
15async fn main() -> Result<(), Box<dyn std::error::Error>> {
16    // Initialize logger
17    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
18
19    // Create client
20    let client = BaiduNetDiskClient::builder().build()?;
21    info!("Client created successfully");
22
23    // Load token from environment
24    client.load_token_from_env()?;
25    info!("Token loaded successfully");
26
27    println!("=== Baidu NetDisk Download Test ===");
28    println!("Enter the remote file path to download (e.g., /upload/test.txt):");
29
30    let stdin = io::stdin();
31    let mut reader = stdin.lock();
32    let mut input = String::new();
33    reader.read_line(&mut input)?;
34    let remote_path = input.trim();
35
36    if remote_path.is_empty() {
37        eprintln!("Error: File path cannot be empty");
38        return Ok(());
39    }
40
41    // Step 1: Get file info (to obtain fs_id)
42    println!("\n--- Step 1: Get file info (to obtain fs_id) ---");
43    println!("Press Enter to continue...");
44    reader.read_line(&mut String::new())?;
45
46    let file_info = client.file().get_file_info(remote_path).await?;
47    let file_size = file_info.size.unwrap_or(0);
48    let fs_id = file_info.fs_id.ok_or_else(|| "File has no fs_id")?;
49    let file_meta = client.file().get_file_meta(fs_id).await?;
50
51    println!("File Info:");
52    println!("  Name: {}", file_info.name);
53    println!("  Path: {}", file_info.path);
54    println!(
55        "  Size: {} bytes ({:.2} MB)",
56        file_size,
57        file_size as f64 / (1024.0 * 1024.0)
58    );
59    println!("  FS ID: {:?}", file_info.fs_id);
60
61    // Step 2: Single-threaded download (skip for large files > 50MB)
62    println!("\n--- Step 2: Single-threaded download ---");
63    if file_size > 50 * 1024 * 1024 {
64        println!(
65            "File size {} bytes exceeds 50MB, skipping single-threaded download...",
66            file_size
67        );
68    } else {
69        println!("Press Enter to continue...");
70        reader.read_line(&mut String::new())?;
71
72        let single_save_path = format!("./download_single_{}", file_info.name);
73        let start_time = Instant::now();
74
75        match client
76            .download()
77            .download_single(remote_path, &single_save_path)
78            .await
79        {
80            Ok(_) => {
81                let duration = start_time.elapsed();
82                print_download_stats("Single-threaded", file_size, duration);
83                println!("Single-threaded download successful: {}", single_save_path);
84            }
85            Err(e) => eprintln!("Single-threaded download failed: {}", e),
86        }
87    }
88
89    // Step 3: Producer-consumer parallel download (queue-based)
90    println!("\n--- Step 3: Parallel download (Producer-Consumer queue-based) ---");
91    println!("Press Enter to continue...");
92    reader.read_line(&mut String::new())?;
93
94    let parallel_save_path = format!("./download_parallel_{}", file_info.name);
95    let start_time = Instant::now();
96
97    match client
98        .download()
99        .download_parallel_multi_threaded(&file_meta, &parallel_save_path, Some(12))
100        .await
101    {
102        Ok(_) => {
103            let duration = start_time.elapsed();
104            print_download_stats("Parallel (Producer-Consumer)", file_size, duration);
105            println!("Parallel download successful: {}", parallel_save_path);
106        }
107        Err(e) => eprintln!("Parallel download failed: {}", e),
108    }
109
110    // Step 4: Auto download (recommended)
111    println!("\n--- Step 4: Auto download (recommended) ---");
112    println!("Press Enter to continue...");
113    reader.read_line(&mut String::new())?;
114
115    let auto_save_path = format!("./download_auto_{}", file_info.name);
116    let start_time = Instant::now();
117
118    match client
119        .download()
120        .auto_download(remote_path, &auto_save_path)
121        .await
122    {
123        Ok(_) => {
124            let duration = start_time.elapsed();
125            print_download_stats("Auto download", file_size, duration);
126            println!("Auto download successful: {}", auto_save_path);
127        }
128        Err(e) => eprintln!("Auto download failed: {}", e),
129    }
130
131    println!("\n=== Download test completed ===");
132
133    Ok(())
134}
135
136/// Print download statistics
137fn print_download_stats(method: &str, file_size: u64, duration: Duration) {
138    let seconds = duration.as_secs_f64();
139    let mb_per_sec = if seconds > 0.0 {
140        (file_size as f64 / (1024.0 * 1024.0)) / seconds
141    } else {
142        0.0
143    };
144
145    println!("{} Download Stats:", method);
146    println!("  Duration: {:.2} seconds", seconds);
147    println!("  Speed: {:.2} MB/s", mb_per_sec);
148}