//! Real Local Image Upload Test //! //! This example demonstrates how to upload your actual local image file //! and use it with the AI Model Face & Hair Detail Fix template. use std::collections::HashMap; use std::path::Path; use std::sync::Arc; use comfyui_sdk::{ ComfyUIClient, ComfyUIClientConfig, ExecutionOptions, AI_MODEL_FACE_HAIR_FIX_TEMPLATE }; use comfyui_sdk::utils::SimpleCallbacks; use serde_json::json; /// Test with real local image upload async fn test_with_real_local_image() -> Result<(), Box> { println!("šŸš€ Starting Real Local Image Upload Test"); // Initialize client let mut client = ComfyUIClient::new(ComfyUIClientConfig { base_url: "http://192.168.0.193:8188".to_string(), ..Default::default() })?; // Connect to ComfyUI server println!("šŸ“” Connecting to ComfyUI server..."); client.connect().await?; println!("āœ… Connected successfully!"); // Register the template println!("šŸ“ Registering AI Model Face & Hair Fix template..."); client.templates().register_from_data(AI_MODEL_FACE_HAIR_FIX_TEMPLATE.clone())?; let template = client.templates_ref() .get_by_id(&AI_MODEL_FACE_HAIR_FIX_TEMPLATE.metadata.id) .ok_or("Failed to register template")?; println!("āœ… Template registered!"); // Your actual local image path let local_image_path = "20250808-111737.png"; println!("\nšŸ“¤ Uploading your image: {}", local_image_path); println!("ā³ This may take a moment depending on file size and network speed..."); match upload_and_execute(&client, template, local_image_path).await { Ok(_) => println!("āœ… Upload and execution completed successfully!"), Err(e) => { println!("\nšŸ’„ Upload/Execution failed: {}", e); show_troubleshooting_tips(&e); } } // Disconnect println!("\nšŸ”Œ Disconnecting from ComfyUI server..."); client.disconnect().await?; println!("šŸ‘‹ Disconnected successfully!"); Ok(()) } /// Upload image and execute template async fn upload_and_execute( client: &ComfyUIClient, template: &comfyui_sdk::WorkflowTemplate, image_path: &str, ) -> Result<(), Box> { // Step 1: Upload image to ComfyUI server println!("\nšŸ”„ Step 1: Uploading image to ComfyUI server..."); if !Path::new(image_path).exists() { return Err(format!("File not found: {}", image_path).into()); } let upload_response = client.upload_image(image_path, false).await?; let uploaded_filename = upload_response.name; println!("āœ… Upload successful! Server filename: {}", uploaded_filename); // Step 2: Execute AI Model Face & Hair Enhancement println!("\nšŸ”„ Step 2: Executing AI Model Face & Hair Enhancement..."); // Create execution callbacks let callbacks = Arc::new( SimpleCallbacks::new() .with_progress(|progress| { let percentage = (progress.progress as f64 / progress.max as f64 * 100.0) as u32; println!("ā³ Progress: {}% ({}/{}) - Node: {}", percentage, progress.progress, progress.max, progress.node_id); }) .with_executing(|node_id| { println!("šŸ”„ Executing node: {}", node_id); }) .with_executed(|result| { println!("āœ… Node completed - Prompt ID: {}", result.prompt_id); }) .with_error(|error| { println!("āŒ Execution error: {}", error.message); }) ); // Prepare parameters let mut parameters = HashMap::new(); parameters.insert("input_image".to_string(), json!(uploaded_filename)); parameters.insert("face_prompt".to_string(), json!("beautiful woman, perfect skin, detailed facial features, professional photography")); parameters.insert("face_denoise".to_string(), json!("0.25")); let execution_options = ExecutionOptions { timeout: Some(std::time::Duration::from_secs(180)), // 3 minutes timeout priority: None, }; let result = client.execute_template_with_callbacks( template, parameters, execution_options, callbacks, ).await?; if result.success { println!("\nšŸŽ‰ AI Model Enhancement completed successfully!"); println!("šŸ“Š Total execution time: {}ms ({:.1}s)", result.execution_time, result.execution_time as f64 / 1000.0); println!("šŸ†” Prompt ID: {}", result.prompt_id); if let Some(outputs) = &result.outputs { println!("\nšŸ“ Generated outputs:"); println!("{}", serde_json::to_string_pretty(outputs)?); // Convert outputs to HTTP URLs let image_urls = client.outputs_to_urls(outputs); println!("\nšŸ–¼ļø Enhanced Image URLs:"); for (index, url) in image_urls.iter().enumerate() { println!(" {}. {}", index + 1, url); } println!("\nšŸ’” How to use these URLs:"); println!(" - Copy the URL and paste in your browser to view"); println!(" - Right-click and \"Save As\" to download"); println!(" - Use in your application to display the enhanced image"); } } else { println!("\nāŒ AI Model Enhancement failed!"); if let Some(error) = &result.error { println!("Error details: {}", error.message); } } Ok(()) } /// Show troubleshooting tips based on error fn show_troubleshooting_tips(error: &Box) { let error_msg = error.to_string(); if error_msg.contains("File not found") || error_msg.contains("No such file") { println!("\nšŸ’” Troubleshooting Tips:"); println!("1. šŸ” Check if the file path is correct"); println!("2. šŸ“ Make sure the file exists at the specified location"); println!("3. šŸ” Ensure you have read permissions for the file"); println!("4. šŸ“ Try using absolute path: /home/user/images/20250808-111737.png"); println!("5. šŸ–¼ļø Verify the file is a valid image format (PNG, JPG, etc.)"); } else if error_msg.contains("Failed to upload") || error_msg.contains("HTTP") { println!("\nšŸ’” Network/Server Issues:"); println!("1. 🌐 Check if ComfyUI server is running and accessible"); println!("2. šŸ“” Verify network connection to the server"); println!("3. šŸ’¾ Check if server has enough disk space"); println!("4. šŸ”’ Ensure server allows file uploads"); } } /// Alternative method using one-step upload and execute (conceptual) async fn test_one_step_method() -> Result<(), Box> { println!("\n\nšŸš€ Testing One-Step Method (Upload + Execute)"); let mut client = ComfyUIClient::new(ComfyUIClientConfig { base_url: "http://192.168.0.193:8188".to_string(), ..Default::default() })?; client.connect().await?; client.templates().register_from_data(AI_MODEL_FACE_HAIR_FIX_TEMPLATE.clone())?; let template = client.templates_ref() .get_by_id(&AI_MODEL_FACE_HAIR_FIX_TEMPLATE.metadata.id) .ok_or("Failed to register template")?; let local_image_path = "20250808-111737.png"; println!("šŸ”„ One-step upload and execute..."); // For now, we'll implement this as upload + execute since we don't have // a dedicated one-step method yet match upload_and_execute_one_step(&client, template, local_image_path).await { Ok(_) => println!("šŸŽ‰ One-step method completed successfully!"), Err(e) => println!("āš ļø One-step method failed: {}", e), } client.disconnect().await?; Ok(()) } /// One-step upload and execute (simplified version) async fn upload_and_execute_one_step( client: &ComfyUIClient, template: &comfyui_sdk::WorkflowTemplate, image_path: &str, ) -> Result<(), Box> { // Upload image let upload_response = client.upload_image(image_path, false).await?; // Create simple callbacks let callbacks = Arc::new( SimpleCallbacks::new() .with_progress(|progress| { let percentage = (progress.progress as f64 / progress.max as f64 * 100.0) as u32; println!("ā³ Progress: {}% - Node: {}", percentage, progress.node_id); }) ); // Execute template let mut parameters = HashMap::new(); parameters.insert("input_image".to_string(), json!(upload_response.name)); parameters.insert("face_prompt".to_string(), json!("stunning model, flawless skin, professional photography, high quality")); parameters.insert("face_denoise".to_string(), json!("0.3")); let result = client.execute_template_with_callbacks( template, parameters, ExecutionOptions { timeout: Some(std::time::Duration::from_secs(180)), priority: None, }, callbacks, ).await?; if result.success { if let Some(outputs) = &result.outputs { let image_urls = client.outputs_to_urls(outputs); println!("šŸ–¼ļø Result URLs: {:?}", image_urls); } } Ok(()) } /// Show usage examples fn show_usage_examples() { println!("\nšŸ“š Complete Usage Guide for Local Images:"); println!(""); println!("šŸ”§ Basic Setup:"); println!("```rust"); println!("use comfyui_sdk::{{ComfyUIClient, ComfyUIClientConfig, AI_MODEL_FACE_HAIR_FIX_TEMPLATE}};"); println!(""); println!("let mut client = ComfyUIClient::new(ComfyUIClientConfig {{"); println!(" base_url: \"http://your-comfyui-server:8188\".to_string(),"); println!(" ..Default::default()"); println!("}});"); println!("```"); println!(""); println!("šŸ“¤ Method 1 - Manual Upload:"); println!("```rust"); println!("// Upload image first"); println!("let upload_response = client.upload_image("); println!(" \"/path/to/your/image.png\", false"); println!(").await?;"); println!(""); println!("// Then execute template"); println!("let result = client.execute_template(template, parameters, options).await?;"); println!("```"); println!(""); println!("šŸš€ Method 2 - Combined Upload and Execute:"); println!("```rust"); println!("// Upload and execute in sequence"); println!("let upload_response = client.upload_image(image_path, false).await?;"); println!("let mut parameters = HashMap::new();"); println!("parameters.insert(\"input_image\".to_string(), json!(upload_response.name));"); println!("let result = client.execute_template_with_callbacks("); println!(" template, parameters, options, callbacks"); println!(").await?;"); println!("```"); } /// Run all tests async fn run_all_tests() -> Result<(), Box> { show_usage_examples(); test_with_real_local_image().await?; // Uncomment to test one-step method as well // test_one_step_method().await?; Ok(()) } #[tokio::main] async fn main() -> Result<(), Box> { run_all_tests().await } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_show_usage_examples() { show_usage_examples(); // This test just ensures the function runs without panicking } }