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 58
use std::fs::File; use std::io::{self, stderr, Read, Write}; use std::error::Error; use std::time::Duration; use hyper::status::StatusCode; use hyper::Client; use hyper::net::HttpsConnector; use hyper_rustls::TlsClient; use hyper::error::Error as HyperError; use hyper::header::ContentLength; use pbr::{ProgressBar, Units}; pub fn download(remote_path: &str, local_path: &str) -> io::Result<()> { let mut stderr = stderr(); write!(stderr, "* Requesting {}\n", remote_path)?; let mut client = Client::with_connector(HttpsConnector::new(TlsClient::new())); client.set_read_timeout(Some(Duration::new(5, 0))); client.set_write_timeout(Some(Duration::new(5, 0))); let mut response = match client.get(remote_path).send() { Ok(response) => response, Err(HyperError::Io(err)) => return Err(err), Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err.description())) }; match response.status { StatusCode::Ok => { let mut count = 0; let length = response.headers.get::<ContentLength>().map_or(0, |h| h.0 as usize); let mut file = File::create(&local_path)?; let mut pb = ProgressBar::new(length as u64); pb.set_units(Units::Bytes); loop { let mut buf = [0; 8192]; let res = response.read(&mut buf)?; if res == 0 { break; } count += file.write(&buf[.. res])?; pb.set(count as u64); } let _ = write!(stderr, "\n"); file.sync_all()?; Ok(()) }, _ => { let _ = write!(stderr, "* Failure {}\n", response.status); Err(io::Error::new(io::ErrorKind::NotFound, format!("{} not found", remote_path))) } } }