※Rust勉強中のため、プログラムが最適かどうかは不明です・・・。特にエラー処理の作法については試行錯誤中です。より良い書き方があれば、そちらを参考にしてください。
CODE
use std::fs::File; use std::io::{Write}; use std::io::{BufRead, BufReader}; #[tokio::main] async fn main() -> Result<(), Box> { let max_download_num=10; let file_name="download.csv"; let sep="\t"; let mut data_from; let mut file_to; let mut no:i32=0; let mut li:i32=0; for result in BufReader::new(File::open(file_name)?).lines() { if li>=max_download_num { break; } li=li+1; let line:String = result?; let v: Vec<&str> = line.split(sep).collect(); if v.len()<2 { println!("Line No.{} skipped.", li); continue; } data_from=v[0]; file_to=v[1]; let resp=reqwest::get(data_from).await; if let Err(e) = resp { println!("Line No.{} Access Error : URL={} ",li,data_from); if e.is_redirect() { if let Some(final_stop) = e.url() { println!("redirect loop at {}", final_stop); } } else if e.is_timeout() { println!("time out"); } else if e.is_status() { let code=e.status(); println!("status code = {}",code.unwrap()); } else{ println!("Unknown Error"); } continue; } let _data=resp.unwrap().bytes().await; if let Err(_) = _data { continue; } let _buf = _data.unwrap(); no=no+1; println!("{} Received... {}",no,data_from); let fresp = File::create(file_to); if let Err(_) = fresp { println!("Line No.{} File create Error(No.{} was received but canceled.)...{}",li,no,file_to); no = no-1; continue; } let mut file = fresp.unwrap(); file.write_all(&_buf)?; file.flush()?; println!("{} Written ... {}",no,file_to); } println!("Done. {} line(s) processed, {} file(s) downloaded.",li,no); Ok(()) }
download.csvの例は以下の通り。
https://example.com/test.pdf test.pdf https://example2.net/picture.jpg picture.jpg http://example3.org/sample.png sample.png
Cargo.toml には、以下を追加。
[dependencies] reqwest = { version = "0.10" } tokio = { version = "0.2", features = ["full"] }