comfyui_api/api/
upload.rs1use reqwest::{multipart, Url};
2use serde::{Deserialize, Serialize};
3
4#[derive(thiserror::Error, Debug)]
6#[non_exhaustive]
7pub enum UploadApiError {
8 #[error("Failed to parse endpoint URL")]
10 ParseError(#[from] url::ParseError),
11 #[error("Failed to set MIME type")]
13 SetMimeStrFailed(#[source] reqwest::Error),
14 #[error("Failed to send request")]
16 RequestFailed(#[from] reqwest::Error),
17 #[error("Parsing response failed")]
19 InvalidResponse(#[source] reqwest::Error),
20 #[error("Failed to get response data")]
22 GetDataFailed(#[source] reqwest::Error),
23 #[error("Failed to upload image: {status}: {error}")]
25 UploadImageFailed {
26 status: reqwest::StatusCode,
27 error: String,
28 },
29}
30
31type Result<T> = std::result::Result<T, UploadApiError>;
32
33#[derive(Serialize, Deserialize, Debug, Clone)]
35pub struct ImageUpload {
36 pub name: String,
38 pub subfolder: String,
40 #[serde(rename = "type")]
42 pub folder_type: String,
43}
44
45#[derive(Clone, Debug)]
47pub struct UploadApi {
48 client: reqwest::Client,
49 endpoint: Url,
50}
51
52impl UploadApi {
53 pub fn new<S>(client: reqwest::Client, endpoint: S) -> Result<Self>
65 where
66 S: AsRef<str>,
67 {
68 Ok(Self::new_with_url(client, Url::parse(endpoint.as_ref())?))
69 }
70
71 pub fn new_with_url(client: reqwest::Client, endpoint: Url) -> Self {
82 Self { client, endpoint }
83 }
84
85 pub async fn image(&self, image: Vec<u8>) -> Result<ImageUpload> {
96 let file = multipart::Part::bytes(image)
97 .file_name("image.png")
98 .mime_str("image/png")
99 .map_err(UploadApiError::SetMimeStrFailed)?;
100 let form = multipart::Form::new().part("image", file);
101 let response = self
102 .client
103 .post(self.endpoint.clone().join("image")?)
104 .multipart(form)
105 .send()
106 .await
107 .map_err(UploadApiError::RequestFailed)?;
108 if response.status().is_success() {
109 return response
110 .json()
111 .await
112 .map_err(UploadApiError::InvalidResponse);
113 }
114 let status = response.status();
115 let text = response
116 .text()
117 .await
118 .map_err(UploadApiError::GetDataFailed)?;
119 Err(UploadApiError::UploadImageFailed {
120 status,
121 error: text,
122 })
123 }
124}