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,35 +121,36 @@ 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) .create(true)
.create(true) .truncate(true)
.truncate(true) .mode(0o770)
.mode(0o770) .open(path)?;
.open(path)?;
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;
} }
file_buffer.write_all(&buf); bytes += count;
} file_buffer.write_all(&buf);
file_buffer.flush(); }
Ok(filename.to_string()) Ok((filename.to_string(), bytes))
})
} }
// 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