Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload image issue #37

Open
DhvaniBhesaniya opened this issue Oct 8, 2024 · 5 comments
Open

Upload image issue #37

DhvaniBhesaniya opened this issue Oct 8, 2024 · 5 comments

Comments

@DhvaniBhesaniya
Copy link

DhvaniBhesaniya commented Oct 8, 2024

i am using the upload method just as instructed but i am getting this parse error. uploading is working fine , in the cloudinary it is being uploaded. i am using data url as a source to upload the image.

here is the error :
"
Upload result :: , Err(failed to parse:

{"asset_id":"c49b1d4902a9dfc2bfee942a38d675c0","public_id":"pwoyepnl4re9skaban5j","version":1728368129,"version_id":"d12154246f5b4b4fe949d8f6ddb8d59f","signature":"209f3fc898796e3d82d59cc6e193f4c544aa39cb","width":223,"height":226,"format":"png","resource_type":"image","created_at":"2024-10-08T06:15:29Z","tags":[],"bytes":4824,"type":"upload","etag":"0652a25b4542ff8a0312f814c6c9a8b1","placeholder":false,"url":"http://res.cloudinary.com/djigcn0dy/image/upload/v1728368129/pwoyepnl4re9skaban5j.png","secure_url":"https://res.cloudinary.com/djigcn0dy/image/upload/v1728368129/pwoyepnl4re9skaban5j.png","asset_folder":"","display_name":"pwoyepnl4re9skaban5j","api_key":"4273989199567"}

Caused by:
data did not match any variant of untagged enum UploadResult)
"

for now i have done like if it is ok then from the success response i will takew the secure url , but if this error comes i am extracting the secure url from the error msg, which in coding sense not good , can you help me to solve this error ,

here below is my code.

pub async fn upload_image_to_cloudinary(profile_img: &str) -> Result<String, String> {
let cloud_name = gett::("CLOUDINARY_CLOUD_NAME");
let api_key = gett::("CLOUDINARY_API_KEY");
let api_secret = gett::("CLOUDINARY_API_SECRET");

let options = UploadOptions::new();
let upload = Upload::new(
    api_key.to_string(),
    cloud_name.to_string(),
    api_secret.to_string(),
);

// Upload the image to Cloudinary
let upload_result = upload
    .image(Source::DataUrl(profile_img.into()), &options)
    .await;

println!("Upload result :: , {:?}", upload_result);

match upload_result {
    // If successful, return the secure URL
    Ok(result) => {
        if let UploadResult::Success(response) = result {
            Ok(response.secure_url)
        } else {
            Err("Upload failed, but no valid URL returned.".to_string())
        }
    }
    // Handle errors
    Err(e) => {
        // Attempt to parse and extract the secure_url from the error message
        let error_message = format!("{:?}", e);

        // Use regex to find the secure_url in the error message
        let re = Regex::new(r#""secure_url":"(https://[^"]+)""#).unwrap();
        if let Some(captures) = re.captures(&error_message) {
            if let Some(secure_url) = captures.get(1) {
                return Ok(secure_url.as_str().to_string());
            }
        }

        Err("Failed to extract secure_url from error".to_string())
    }
}

}
can you check if there is any problem ?.

@Lurk
Copy link
Owner

Lurk commented Oct 8, 2024

I see they changed the response schema in the documentation and the error message you posted, but I can not get a response in that shape.

Anyway, I know how to fix that (one more enum variant here: https://github.com/Lurk/cloudinary_rs/blob/main/src/upload/result.rs#L27). I'm still trying to figure out how to test, though.

@DhvaniBhesaniya
Copy link
Author

i have trield to update the code structure here base on the response , and its working fine, with a success response casting to UploadResult success Response,

here is what i have tries to change and update .

#[derive(Clone, Deserialize, Debug)]
pub struct Eager {
pub transformation: Option,
pub width: Option,
pub height: Option,
pub bytes: Option,
pub format: Option,
pub url: Option,
pub secure_url: Option,
}

#[derive(Clone, Deserialize, Debug)]
pub struct Response {
pub asset_id: String,
pub public_id: String,
pub version: usize,
pub version_id: String,
pub signature: String,
pub width: usize,
pub height: usize,
pub format: String,
pub resource_type: String,
#[serde(deserialize_with = "deserialize_from_str")]
pub created_at: DateTime,
pub tags: Vec,
pub bytes: usize,
pub r#type: String,
pub etag: String,
pub placeholder: bool,
pub url: String,
pub secure_url: String,
pub folder: Option,
pub overwritten: Option,
pub original_filename: Option,
pub original_extension: Option,
pub api_key: String,
pub eager: Option<Vec>,
}

pub async fn image(&self, src: Source, options: &UploadOptions<'_>) -> Result {
let client = Client::new();
let file = match src {
Source::Path(path) => prepare_file(&path).await?,
Source::Url(url) => Part::text(url.as_str().to_string()),
Source::DataUrl(base64) => Part::text(base64),
};
let multipart = self.build_form_data(options).part("file", file);
let url = format!(
"https://api.cloudinary.com/v1_1/{}/image/upload",
self.cloud_name
);

    // Send the request
    let response = client
    .post(&url)
    .multipart(multipart)
    .send()
    .await
    .context(format!("upload to {}", url))?;

// Capture the response status before consuming the response
let status = response.status();

// Get the response text (this consumes the response)
let text = response.text().await?;
println!("Cloudinary response text: {:?}", text);

// Check if the response was successful based on the saved status
if status.is_success() {
    // Parse success response into UploadResult::Success
    let parsed_response: Response = serde_json::from_str(&text)
        .context(format!("Failed to parse Cloudinary success response:\n\n {}", text))?;
    return Ok(UploadResult::Success(Box::new(parsed_response)));
}


    // Otherwise, parse it as an error
    let parsed_error: Error = serde_json::from_str(&text)
        .context(format!("Failed to parse Cloudinary error response:\n\n {}", text))?;
    Ok(UploadResult::Error(Box::new(parsed_error)))
}

i have changes the structure and upload image function.
see if this helps you.

@Lurk
Copy link
Owner

Lurk commented Oct 9, 2024

Hey @DhvaniBhesaniya, please check the latest version. https://crates.io/crates/cloudinary/0.6.0
Note that upload_result from your first example has a new enum variant with a new response shape.

I haven't found where this change is documented, but all new Cloudinary accounts get the response in the new shape, while old accounts still get it in the old shape.

@DhvaniBhesaniya
Copy link
Author

DhvaniBhesaniya commented Oct 10, 2024

According to you new version update
i am still getting parse error here " ResponseWithImageMetadata "

ERROR - failed to parse:

{"asset_id":"c38a161953bc4a6c7472a7c04a44577b","public_id":"oujlo7tngcrq9pneavst","version":1728536861,"version_id":"4c797b517cf0d5adbf3d0d196d3bfcb0","signature":"149de0e119e1d7970782d16506cfb87c4706000f","width":274,"height":184,"format":"jpg","resource_type":"image","created_at":"2024-10-10T05:07:41Z","tags":[],"bytes":4365,"type":"upload","etag":"f2e60e6cfdb2d4e3e48f2a117faaa34d","placeholder":false,"url":"http://res.cloudinary.com/djigcn0dy/image/upload/v1728536861/oujlo7tngcrq9pneavst.jpg","secure_url":"https://res.cloudinary.com/djigcn0dy/image/upload/v1728536861/oujlo7tngcrq9pneavst.jpg","asset_folder":"","display_name":"oujlo7tngcrq9pneavst","api_key":"427982931967"}

Caused by:
data did not match any variant of untagged enum UploadResult

i have tries to change the response structure according to the cloudinary response schema ,

#37 (comment)

see comment .

@Lurk
Copy link
Owner

Lurk commented Oct 10, 2024

Hey, @DhvaniBhesaniya, please check the next version https://crates.io/crates/cloudinary/0.7.0 😀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants