Rust实现图片上传功能
使用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
}