使用Rust来实现图片的上传功能主要为上传端的代码,用于typora的图片云端存储功能

依赖

tokio = { version = "1.35.1", features = ["rt", "rt-multi-thread", "macros"] }
reqwest = { version = "0.11", features = ["multipart", "json"] }
serde = "1.0"
serde_json = "1.0"

代码

use std::env;
use std::path::{Path, PathBuf};
use reqwest::{Client, multipart};

#[tokio::main]
async fn main() {
    // 获取当前工作目录
    let current_dir = match env::current_dir() {
        Ok(dir) => dir,
        Err(err) => {
            eprintln!("Error getting current directory: {:?}", err);
            std::process::exit(1);
        }
    };

    // 获取命令行参数,即图像路径
    let args: Vec<String> = env::args().collect();

    if args.len() < 2 {
        eprintln!("Usage: {} <image-path-1> <image-path-2> ...", args[0]);
        std::process::exit(1);
    }

    // 存储成功上传图像的远程URL
    let mut success_urls = Vec::new();

    // 处理图像上传
    for image_path in &args[1..] {
        // 构建绝对路径
        let absolute_path = current_dir.join(Path::new(image_path));

        println!("Uploading image: {}", absolute_path.display());
        if let Some(remote_url) = upload_image(absolute_path.clone()).await {
            success_urls.push(remote_url);
            println!("Upload Successful for {}", absolute_path.display());
        } else {
            eprintln!("Upload Failed for {}", absolute_path.display());
        }
    }

    // 打印成功上传的远程URL
    if !success_urls.is_empty() {
        println!("Upload Success:");
        for url in success_urls {
            println!("{}", url);
        }
    }
}

// 图像上传,调用接口并返回远程URL
async fn upload_image(image_path: PathBuf) -> Option<String> {
    // 读取文件内容
    let file_content = match std::fs::read(&image_path) {
        Ok(content) => content,
        Err(err) => {
            eprintln!("Error reading file {}: {:?}", image_path.display(), err);
            return None;
        }
    };

    // 获取文件名的字符串表示
    let file_name_str = image_path.file_name()?.to_string_lossy().into_owned();

    // 构建文件表单项
    let form = multipart::Form::new()
        .part("file", multipart::Part::bytes(file_content).file_name(file_name_str));

    // 构建上传URL
    let upload_url = "https://liershuai.com/aa/bb/cc";

    // 发送POST请求
    let response = match Client::new().post(upload_url).multipart(form).send().await {
        Ok(res) => res,
        Err(err) => {
            eprintln!("Error sending request: {:?}", err);
            return None;
        }
    };

    // 处理响应
    if response.status().is_success() {
        let result: serde_json::Value = match response.json().await {
            Ok(value) => value,
            Err(err) => {
                eprintln!("Error parsing JSON response: {:?}", err);
                return None;
            }
        };
        if let Some(file_url) = result["data"]["file_url"].as_str() {
            return Some(file_url.to_string());
        }
    } else {
        eprintln!("Error response status: {}", response.status());
    }

    None
}