pkg/net_backend/
reqwest_backend.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use std::{
    cell::RefCell,
    fs::File,
    io::{Read, Write},
    path::Path,
    rc::Rc,
    time::Duration,
};

use super::{Callback, DownloadBackend, DownloadError};

#[derive(Clone)]
pub struct ReqwestBackend {
    client: reqwest::blocking::Client,
}

impl DownloadBackend for ReqwestBackend {
    fn new() -> Result<Self, DownloadError> {
        let client = reqwest::blocking::Client::builder()
            .brotli(true)
            .timeout(Duration::new(5, 0))
            .build()?;
        Ok(Self { client })
    }

    fn download(
        &self,
        remote_path: &str,
        local_path: &Path,
        callback: Rc<RefCell<dyn Callback>>,
    ) -> Result<(), DownloadError> {
        let mut callback = callback.borrow_mut();

        let mut resp = self.client.get(remote_path).send()?.error_for_status()?;

        let len: u64 = resp.content_length().unwrap_or(0);

        let mut output = File::create(local_path)?;

        callback.start_download(len, remote_path);

        let mut data = [0; 8192];
        loop {
            let count = resp.read(&mut data)?;
            output.write(&data[..count])?;
            if count == 0 {
                break;
            }
            callback.increment_downloaded(count);
        }
        output.flush()?;

        callback.end_download();

        Ok(())
    }
}