Remove into-file option + more refactoring
This commit is contained in:
parent
88f23ae568
commit
c9ac3dd683
@ -18,14 +18,6 @@ pub struct CLIArgs {
|
||||
)]
|
||||
pub outdir: PathBuf,
|
||||
|
||||
#[clap(
|
||||
short = 'i',
|
||||
long = "into-file",
|
||||
value_name = "FILENAME",
|
||||
help = "Force filename. This only works for single file downloads",
|
||||
)]
|
||||
pub into_file: Option<PathBuf>,
|
||||
|
||||
#[clap(
|
||||
short = 'n',
|
||||
long = "num-files",
|
||||
|
||||
@ -95,10 +95,7 @@ pub async fn download_feedback_chunks(
|
||||
) -> Result<()> {
|
||||
let mut content_length = match content_length {
|
||||
Some(it) => it,
|
||||
None => {
|
||||
let (content_length, _) = http_get_filesize_and_range_support(url).await?;
|
||||
content_length
|
||||
}
|
||||
None => http_get_filesize_and_range_support(url).await?.filesize,
|
||||
};
|
||||
|
||||
// Send the HTTP request to download the given link
|
||||
@ -226,7 +223,7 @@ pub async fn download_feedback_multi(
|
||||
) -> Result<()> {
|
||||
let content_length = match content_length {
|
||||
Some(it) => it,
|
||||
None => http_get_filesize_and_range_support(url).await?.0,
|
||||
None => http_get_filesize_and_range_support(url).await?.filesize,
|
||||
};
|
||||
|
||||
// Create zeroed file with 1 byte too much. This will be truncated on download
|
||||
@ -379,40 +376,45 @@ pub async fn download_feedback_multi(
|
||||
async fn create_zeroed_file(file: &Path, filesize: usize) -> Result<()> {
|
||||
let ofile = tokio::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
// Open in write mode
|
||||
.write(true)
|
||||
// Delete and overwrite the file
|
||||
.truncate(true)
|
||||
.open(file)
|
||||
.await?;
|
||||
|
||||
ofile.set_len(filesize as u64).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn http_get_filesize_and_range_support(url: &str) -> Result<(u64, bool)> {
|
||||
pub struct HttpFileInfo {
|
||||
pub filesize: u64,
|
||||
pub range_support: bool,
|
||||
pub filename: String,
|
||||
}
|
||||
|
||||
pub async fn http_get_filesize_and_range_support(url: &str) -> Result<HttpFileInfo> {
|
||||
let resp = reqwest::Client::new().head(url).send().await?;
|
||||
|
||||
if let Some(filesize) = resp.headers().get(reqwest::header::CONTENT_LENGTH) {
|
||||
if let Ok(val_str) = filesize.to_str() {
|
||||
if let Ok(val) = val_str.parse::<u64>() {
|
||||
let mut range_supported = false;
|
||||
let filesize = resp
|
||||
.headers()
|
||||
.get(reqwest::header::CONTENT_LENGTH)
|
||||
.and_then(|it| it.to_str().unwrap().parse::<u64>().ok())
|
||||
.ok_or(DlError::ContentLengthUnknown)?;
|
||||
|
||||
if let Some(range) = resp.headers().get(reqwest::header::ACCEPT_RANGES) {
|
||||
if let Ok(range) = range.to_str() {
|
||||
if range == "bytes" {
|
||||
range_supported = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
let range = resp
|
||||
.headers()
|
||||
.get(reqwest::header::ACCEPT_RANGES)
|
||||
.and_then(|it| it.to_str().ok());
|
||||
let range_support = matches!(range, Some("bytes"));
|
||||
|
||||
return Ok((val, range_supported));
|
||||
}
|
||||
}
|
||||
}
|
||||
let filename = url_to_filename(url);
|
||||
|
||||
Err(DlError::ContentLengthUnknown.into())
|
||||
let info = HttpFileInfo {
|
||||
filesize,
|
||||
range_support,
|
||||
filename,
|
||||
};
|
||||
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
48
src/main.rs
48
src/main.rs
@ -7,7 +7,6 @@ use std::{
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use download::{download_feedback, download_feedback_multi, http_get_filesize_and_range_support};
|
||||
use futures::future::join_all;
|
||||
use tokio::{
|
||||
fs::create_dir_all,
|
||||
@ -16,11 +15,12 @@ use tokio::{
|
||||
Mutex,
|
||||
},
|
||||
};
|
||||
use zippy::is_zippyshare_url;
|
||||
|
||||
use crate::{
|
||||
args::CLIArgs,
|
||||
dlreport::{watch_and_print_reports, DlReport, DlReporter, DlStatus},
|
||||
download::{download_feedback, download_feedback_multi, http_get_filesize_and_range_support},
|
||||
zippy::is_zippyshare_url,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
@ -134,71 +134,65 @@ async fn download_job(urls: SyncQueue, reporter: UnboundedSender<DlReport>, cli_
|
||||
dlreq.url.to_string()
|
||||
};
|
||||
|
||||
let file_name = cli_args
|
||||
.into_file
|
||||
.clone()
|
||||
.unwrap_or_else(|| download::url_to_filename(&url).into());
|
||||
|
||||
let into_file: PathBuf = cli_args
|
||||
.outdir
|
||||
.join(Path::new(&file_name))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.into();
|
||||
|
||||
let (filesize, range_supported) = match http_get_filesize_and_range_support(&url).await {
|
||||
Ok((filesize, range_supported)) => (filesize, range_supported),
|
||||
let info = match http_get_filesize_and_range_support(&url).await {
|
||||
Ok(it) => it,
|
||||
Err(_e) => {
|
||||
reporter.send(DlStatus::Message(format!(
|
||||
"Error while querying metadata: {}",
|
||||
url
|
||||
"Error while querying metadata: {url}"
|
||||
)));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let into_file: PathBuf = cli_args
|
||||
.outdir
|
||||
.join(Path::new(&info.filename))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.into();
|
||||
|
||||
// If file with same name is present locally, check filesize
|
||||
if into_file.exists() {
|
||||
let local_filesize = std::fs::metadata(&into_file).unwrap().len();
|
||||
|
||||
if filesize == local_filesize {
|
||||
if info.filesize == local_filesize {
|
||||
reporter.send(DlStatus::Message(format!(
|
||||
"Skipping file '{}': already present",
|
||||
file_name.display()
|
||||
info.filename
|
||||
)));
|
||||
reporter.send(DlStatus::Skipped);
|
||||
continue;
|
||||
} else {
|
||||
reporter.send(DlStatus::Message(format!(
|
||||
"Replacing file '{}': present but not completed",
|
||||
&file_name.display()
|
||||
&info.filename
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
let dl_status = if cli_args.conn_count.get() == 1 {
|
||||
download_feedback(&url, &into_file, reporter.clone(), Some(filesize)).await
|
||||
} else if !range_supported {
|
||||
download_feedback(&url, &into_file, reporter.clone(), Some(info.filesize)).await
|
||||
} else if !info.range_support {
|
||||
reporter.send(DlStatus::Message(format!(
|
||||
"Server does not support range headers. Downloading with single connection: {}",
|
||||
url
|
||||
)));
|
||||
download_feedback(&url, &into_file, reporter.clone(), Some(filesize)).await
|
||||
download_feedback(&url, &into_file, reporter.clone(), Some(info.filesize)).await
|
||||
} else {
|
||||
download_feedback_multi(
|
||||
&url,
|
||||
&into_file,
|
||||
reporter.clone(),
|
||||
cli_args.conn_count.get(),
|
||||
Some(filesize),
|
||||
Some(info.filesize),
|
||||
)
|
||||
.await
|
||||
};
|
||||
|
||||
if dl_status.is_err() {
|
||||
reporter.send(DlStatus::DoneErr {
|
||||
filename: file_name.to_str().unwrap().to_string(),
|
||||
filename: info.filename,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user