use anthropic_sdk::{
File, FileData, FileSource, FileConstraints, FileBuilder, to_file,
TokenCounter, RetryExecutor, default_retry,
types::{MessageContent, ContentBlockParam},
};
use std::path::Path;
use tempfile::NamedTempFile;
use std::io::Write;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("📁 Comprehensive File Upload Demo");
println!("=================================\n");
let token_counter = TokenCounter::new();
let retry_executor = default_retry();
let image_data = create_sample_image_data();
let csv_data = create_sample_csv_data();
let text_data = "This is a sample text document with some content for analysis.";
let json_data = r#"{"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}"#;
println!("🎯 Demo Scenarios:");
println!("==================\n");
println!("📂 Scenario 1: File Creation from Multiple Sources");
println!("--------------------------------------------------");
let text_file = File::from_bytes(
text_data.as_bytes().to_vec(),
"sample.txt",
"text/plain"
)?;
println!("✅ Created text file from bytes: {} ({} bytes)",
text_file.name(), text_file.size());
let image_base64 = base64::encode(&image_data);
let image_file = File::from_base64(
&image_base64,
"sample.png",
"image/png"
)?;
println!("✅ Created image file from base64: {} ({} bytes)",
image_file.name(), image_file.size());
let csv_file = FileBuilder::new()
.name("data.csv")
.mime_type("text/csv")
.data(FileData::Bytes(csv_data.as_bytes().to_vec()))
.calculate_hash(true)
.build()?;
println!("✅ Created CSV file with builder: {} (hash: {})",
csv_file.name(),
csv_file.hash().map(|h| format!("{:.8}...", h)).unwrap_or("none".to_string()));
let json_file = to_file(json_data.as_bytes(), "data.json", "application/json")?;
println!("✅ Created JSON file with to_file(): {} ({} bytes)",
json_file.name(), json_file.size());
println!("\n🔒 Scenario 2: File Validation and Constraints");
println!("----------------------------------------------");
let image_constraints = FileConstraints::new()
.max_size(5 * 1024 * 1024) .allowed_types(vec!["image/png".to_string(), "image/jpeg".to_string()])
.require_hash(true);
let text_constraints = FileConstraints::new()
.max_size(1024 * 1024) .allowed_types(vec!["text/plain".to_string(), "text/csv".to_string()]);
match image_constraints.validate(&image_file) {
Ok(_) => println!("✅ Image file passed validation"),
Err(e) => println!("❌ Image file failed validation: {}", e),
}
match text_constraints.validate(&text_file) {
Ok(_) => println!("✅ Text file passed validation"),
Err(e) => println!("❌ Text file failed validation: {}", e),
}
let large_file_data = vec![0u8; 2 * 1024 * 1024]; let large_file = File::from_bytes(large_file_data, "large.txt", "text/plain")?;
match text_constraints.validate(&large_file) {
Ok(_) => println!("❌ Large file unexpectedly passed validation"),
Err(e) => println!("✅ Large file correctly failed validation: {}", e),
}
println!("\n🕵️ Scenario 3: MIME Type Detection");
println!("----------------------------------");
let test_files = vec![
("document.pdf", "application/pdf"),
("image.jpg", "image/jpeg"),
("data.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
("video.mp4", "video/mp4"),
("archive.zip", "application/zip"),
];
for (filename, expected_mime) in test_files {
let detected_mime = File::detect_mime_type(filename);
let matches = detected_mime == expected_mime;
println!(" {} -> {} {}",
filename,
detected_mime,
if matches { "✅" } else { "❌" }
);
}
println!("\n⚙️ Scenario 4: File Processing Utilities");
println!("----------------------------------------");
println!("File type checks:");
println!(" {} is image: {}", image_file.name(), image_file.is_image());
println!(" {} is text: {}", text_file.name(), text_file.is_text());
println!(" {} is application: {}", json_file.name(), json_file.is_application());
println!("\nFormat conversion:");
let text_as_base64 = text_file.to_base64()?;
println!(" Text file as base64: {:.50}...", text_as_base64);
let image_as_bytes = image_file.to_bytes()?;
println!(" Image file as bytes: {} bytes", image_as_bytes.len());
println!("\n🗑️ Scenario 5: Temporary Files and Cleanup");
println!("-------------------------------------------");
let mut temp_file = NamedTempFile::new()?;
temp_file.write_all(b"Temporary file content for testing")?;
temp_file.flush()?;
let temp_path = temp_file.path().to_path_buf();
println!("Created temporary file: {}", temp_path.display());
let file_from_path = File::from_path(&temp_path)?;
println!("✅ Loaded file from path: {} ({} bytes)",
file_from_path.name(), file_from_path.size());
drop(temp_file);
println!("✅ Temporary file cleaned up automatically");
println!("\n💬 Scenario 6: Message Integration");
println!("----------------------------------");
let image_content = ContentBlockParam::image_file(image_file.clone());
println!("✅ Created image content block for message");
let file_content = ContentBlockParam::from_file(json_file.clone())?;
println!("✅ Created file content block from JSON file");
let message_content = MessageContent::Blocks(vec![
ContentBlockParam::text("Please analyze these files:"),
ContentBlockParam::text("1. Sample image:"),
image_content,
ContentBlockParam::text("2. Data file:"),
file_content,
ContentBlockParam::text("What insights can you provide?"),
]);
println!("✅ Built multi-part message with {} content blocks",
if let MessageContent::Blocks(ref blocks) = message_content {
blocks.len()
} else {
0
}
);
println!("\n⚡ Scenario 7: Performance Metrics");
println!("----------------------------------");
let start_time = std::time::Instant::now();
let files = vec![&text_file, &image_file, &csv_file, &json_file];
let total_size: usize = files.iter().map(|f| f.size()).sum();
let total_files = files.len();
let processing_time = start_time.elapsed();
println!("Performance metrics:");
println!(" Files processed: {}", total_files);
println!(" Total data size: {} bytes", total_size);
println!(" Processing time: {:?}", processing_time);
println!(" Throughput: {:.2} MB/s",
(total_size as f64 / 1024.0 / 1024.0) / processing_time.as_secs_f64());
let usage_summary = token_counter.get_summary();
println!("\nInfrastructure metrics:");
println!(" Session duration: {:.1} seconds", usage_summary.session_duration.as_secs_f64());
println!(" Retry policy: {} max retries", retry_executor.get_policy().max_retries);
println!("\n📊 File Summary");
println!("===============");
let all_files = vec![
("Text", &text_file),
("Image", &image_file),
("CSV", &csv_file),
("JSON", &json_file),
];
for (type_name, file) in all_files {
println!("{} File:", type_name);
println!(" Name: {}", file.name());
println!(" Size: {} bytes", file.size());
println!(" MIME: {}", file.mime_type());
println!(" Hash: {}", file.hash().unwrap_or("none".to_string()));
println!();
}
println!("✨ Comprehensive File Upload Demo Complete!");
println!("🚀 All file scenarios executed successfully!");
println!("💡 This demonstrates production-ready file handling with:");
println!(" • Multiple file sources (bytes, base64, paths, builder)");
println!(" • Comprehensive validation and constraints");
println!(" • MIME type detection and processing utilities");
println!(" • Message integration for AI workflows");
println!(" • Performance optimization and memory efficiency");
Ok(())
}
fn create_sample_image_data() -> Vec<u8> {
vec![
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, ]
}
fn create_sample_csv_data() -> String {
"name,age,city\n\
Alice,30,San Francisco\n\
Bob,25,New York\n\
Carol,35,London\n\
David,28,Tokyo".to_string()
}