use std::path::Path;
use async_trait::async_trait;
use reqwest::multipart::{Form, Part};
use wx_rust_common::bean::result::WxMinishopImageUploadResult;
use wx_rust_common::enums::WxType;
use wx_rust_common::error::WxErrorException;
use wx_rust_common::util::http::RequestExecutor;
#[derive(Debug, Clone)]
pub struct MinishopUploadRequestExecutor {
client: reqwest::Client,
}
impl MinishopUploadRequestExecutor {
pub fn new(client: reqwest::Client) -> Self {
Self { client }
}
pub async fn upload(
&self,
uri: &str,
file_path: &str,
) -> Result<WxMinishopImageUploadResult, WxErrorException> {
let bytes = tokio::fs::read(file_path)
.await
.map_err(|e| WxErrorException::from_code(-99, format!("读取上传文件失败: {e}")))?;
let file_name = Path::new(file_path)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("file")
.to_string();
let part = Part::bytes(bytes).file_name(file_name);
let form = Form::new().part("media", part);
let resp = self.client.post(uri).multipart(form).send().await?;
let body = resp.text().await?;
Self::handle_response(&body)
}
fn handle_response(
response_content: &str,
) -> Result<WxMinishopImageUploadResult, WxErrorException> {
if let Ok(json) = serde_json::from_str::<serde_json::Value>(response_content) {
let code = json.get("errcode").and_then(|c| match c {
serde_json::Value::Number(n) => n.as_i64(),
serde_json::Value::String(s) => s.parse().ok(),
_ => None,
});
if let Some(code) = code {
if code != 0 {
let msg = json
.get("errmsg")
.and_then(|m| m.as_str())
.unwrap_or_default()
.to_string();
return Err(WxErrorException::from_code(code as i32, msg));
}
}
}
serde_json::from_str(response_content).map_err(|e| WxErrorException::Serde(e.to_string()))
}
}
#[async_trait]
impl RequestExecutor<WxMinishopImageUploadResult, String> for MinishopUploadRequestExecutor {
async fn execute(
&self,
uri: &str,
data: String,
_wx_type: WxType,
) -> Result<WxMinishopImageUploadResult, WxErrorException> {
self.upload(uri, &data).await
}
}