use reqwest::blocking::{multipart::Form, Client}; use std::{env, error::Error, fs, io, time::Duration}; fn run() -> Result<(), Box> { let args: Vec = env::args().skip(1).collect(); let mode = args.first().map(String::as_str).unwrap_or("url"); let input = args.get(1).map(String::as_str).unwrap_or("https://example.com/"); let output = args.get(2).map(String::as_str).unwrap_or("output.pdf"); if args.len() > 3 || args.len() == 1 || !matches!(mode, "url" | "file" | "text") { return Err("Usage: pdfcrowd-example [url|file|text INPUT [OUTPUT.pdf]]".into()); } let username = env::var("API_USERNAME")?; let api_key = env::var("API_KEY")?; if username.is_empty() || api_key.is_empty() { return Err("API_USERNAME and API_KEY must not be empty; both may be demo.".into()); } let client = Client::builder() .connect_timeout(Duration::from_secs(30)) .timeout(Duration::from_secs(120)) .redirect(reqwest::redirect::Policy::none()) .build()?; let form = Form::new() .text("input_format", "html") .text("output_format", "pdf") .text("content_viewport_width", "balanced") .text("page_size", "A4"); let form = match mode { "file" => form.file("file", input)?, _ => form.text(mode.to_owned(), input.to_owned()), }; let response = client.post("https://api.pdfcrowd.com/convert/24.04/") .basic_auth(username, Some(api_key)) .multipart(form) .send()?; let status = response.status(); if status != reqwest::StatusCode::OK { let details = response.text()?; return Err(io::Error::other(format!("PDFCrowd returned HTTP {status}: {details}")).into()); } let pdf = response.bytes()?; fs::write(output, &pdf)?; println!("Saved {output}"); Ok(()) } fn main() { if let Err(error) = run() { eprintln!("Conversion failed: {error}"); std::process::exit(1); } }