size of download

pull/6/head
dvkt 5 years ago
parent 43c10f7cd7
commit ea0b8f529b

@ -108,8 +108,9 @@ pub fn fetch(host: &str, port: &str, selector: &str) -> Result<String> {
}) })
} }
// Downloads a binary to disk and returns the path it was saved to. // Downloads a binary to disk.
pub fn download_url(url: &str) -> Result<String> { // Returns the path it was saved to and the size in bytes.
pub fn download_url(url: &str) -> Result<(String, usize)> {
let (_, host, port, sel) = parse_url(url); let (_, host, port, sel) = parse_url(url);
let sel = sel.replace('?', "\t"); // search queries let sel = sel.replace('?', "\t"); // search queries
let filename = sel let filename = sel
@ -120,17 +121,16 @@ pub fn download_url(url: &str) -> Result<String> {
let mut path = std::path::PathBuf::from("."); let mut path = std::path::PathBuf::from(".");
path.push(filename); path.push(filename);
let mut stream = format!("{}:{}", host, port) format!("{}:{}", host, port)
.to_socket_addrs() .to_socket_addrs()
.and_then(|mut socks| socks.next().ok_or_else(|| error!("Can't create socket"))) .and_then(|mut socks| socks.next().ok_or_else(|| error!("Can't create socket")))
.and_then(|sock| TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION)) .and_then(|sock| TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION))
.and_then(|mut stream| { .and_then(|mut stream| {
stream.write(format!("{}\r\n", sel).as_ref()); stream.write(format!("{}\r\n", sel).as_ref());
Ok(stream) Ok(stream)
})?; })
.and_then(|mut stream| {
stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION))?; stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION))?;
stream.set_nonblocking(true)?;
let file = std::fs::OpenOptions::new() let file = std::fs::OpenOptions::new()
.write(true) .write(true)
@ -141,14 +141,16 @@ pub fn download_url(url: &str) -> Result<String> {
let mut file_buffer = BufWriter::new(file); let mut file_buffer = BufWriter::new(file);
let mut buf = [0 as u8; 8]; // read 8 bytes at a time let mut buf = [0 as u8; 8]; // read 8 bytes at a time
let mut bytes = 0;
while let Ok(count) = stream.read(&mut buf) { while let Ok(count) = stream.read(&mut buf) {
if count == 0 { if count == 0 {
break; break;
} }
bytes += count;
file_buffer.write_all(&buf); file_buffer.write_all(&buf);
} }
file_buffer.flush(); Ok((filename.to_string(), bytes))
Ok(filename.to_string()) })
} }
// url parsing states // url parsing states

@ -133,8 +133,12 @@ impl UI {
let url = url.to_string(); let url = url.to_string();
self.spinner("", move || gopher::download_url(&url)) self.spinner("", move || gopher::download_url(&url))
.and_then(|res| res) .and_then(|res| res)
.and_then(|res| { .and_then(|(path, bytes)| {
self.set_status(format!("Download complete! {}", res)); self.set_status(format!(
"Download complete! {} saved to {}",
human_bytes(bytes),
path
));
Ok(()) Ok(())
}) })
} }
@ -478,3 +482,19 @@ pub fn prompt(prompt: &str) -> Option<String> {
None None
} }
} }
fn human_bytes(bytes: usize) -> String {
let (count, tag) = if bytes < 1000 {
(bytes, " bytes")
} else if bytes < 1_000_000 {
(bytes / 1000, "Kb")
} else if bytes < 1_000_000_000 {
(bytes / 1_000_000, "Mb")
} else if bytes < 1_000_000_000_000 {
(bytes / 1_000_000_000, "Gb")
} else {
(bytes, "?b")
};
format!("{}{}", count, tag)
}

Loading…
Cancel
Save