在完成前面的步骤之后,就已经可以在 PNG 文件中编码隐藏信息、解码提取信息、删除指定数据块以及打印所有数据块信息。
接下来让我们来根据图片 URL 来下载图片来进行编码吧。
reqwest 库
reqwest是一个强大的 HTTP 客户端库,它提供了简洁易用的 API,方便开发者发送 HTTP 请求,获取网络资源。
在Cargo.toml
中添加如下依赖:
reqwest = { version = "0.11", features = ["blocking"] }
代码逻辑调整
调整命令行参数
在pngme/pngme_bin/src/main.rs文件中,对命令行参数结构进行了调整。定义了InputArgs结构体,添加了file_path和url两个互斥的可选参数。这使得程序在运行时可以根据用户的输入,决定从本地文件路径还是 URL 获取图片。
#[derive(Parser, Debug)]
struct InputArgs {
#[clap(short = 'f', long = "file-path", conflicts_with = "url")]
file_path: Option<PathBuf>,
#[clap(short = 'u', long = "url", conflicts_with = "file_path")]
url: Option<String>,
}
新增下载图片方法
为了实现从 URL 下载图片,定义了download_image函数。该函数使用reqwest::blocking::get
方法发送 HTTP GET 请求获取图片数据,并将响应数据写入 Vec<u8>
类型的 buffer
中返回。
fn download_image(url: &str) -> Result<Vec<u8>> {
let mut response = get(url)?;
let mut buffer = Vec::new();
response.copy_to(&mut buffer)?;
Ok(buffer)
}
这个函数是实现从 URL 下载图片的核心,它利用reqwest库的功能,将网络上的图片数据成功下载到本地内存中。
功能函数修改
在encode、decode、remove、print_chunks等函数中,根据InputArgs结构体中的file_path或url参数,决定图片数据的来源。例如,在encode函数中:
fn encode(args: EncodeArgs) -> Result<()> {
let buffer = if let Some(url) = &args.input.url {
download_image(url)?
} else {
let mut file = File::open(args.input.file_path.as_ref().unwrap())?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
buffer
};
let mut png = Png::try_from(buffer.as_slice())?;
let chunk_type = ChunkType::from_str(&args.chunk_type)?;
let chunk = Chunk::new(chunk_type, args.message.into_bytes());
png.append_chunk(chunk);
let output_path = if args.input.url.is_some() {
args.output.ok_or_else(|| anyhow::anyhow!("Output path is required when using --url"))?
} else {
args.output.unwrap_or(args.input.file_path.unwrap())
};
let mut output_file = File::create(output_path)?;
output_file.write_all(&png.as_bytes())?;
println!("Message encoded successfully.");
Ok(())
}
这样我们的项目里就可以从网上下载图片了。
具体的命令行:
pngme_bin encode [--url <URL> | --file-path <INPUT_FILE> ] <CHUNK_TYPE> <MESSAGE> [--output <OUTPUT_FILE>]