写一个 Rust 小应用 pngme - 6.处理图片链接

1 阅读2分钟

在完成前面的步骤之后,就已经可以在 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>]