Travailler avec S3 et les stockages cloud en Rust : la bibliothèque aws-sdk-s3
\n\nLes stockages d'objets cloud, tels qu'Amazon S3, sont devenus la norme pour le stockage et la livraison de fichiers, de sauvegardes et de contenu multimédia. Rust, en tant que langage de programmation système, offre des outils puissants et sécurisés pour l'intégration avec ces services. La bibliothèque principale est aws-sdk-s3 — le SDK officiel d'Amazon pour Rust.
Dans cet article, nous allons voir comment configurer un projet, effectuer des opérations de base (téléversement, téléchargement, suppression) et travailler avec des stockages compatibles S3 (par exemple, MinIO ou Yandex Object Storage).
\n\nInstallation et configuration
\n\nAjoutez dans Cargo.toml :
[dependencies]\naws-sdk-s3 = "1.0"\naws-config = "1.0"\ntokio = { version = "1", features = ["full"] }\n\n\nPour l'authentification, on utilise des variables d'environnement ou le fichier ~/.aws/credentials :
export AWS_ACCESS_KEY_ID="your_access_key"\nexport AWS_SECRET_ACCESS_KEY="your_secret_key"\nexport AWS_DEFAULT_REGION="us-east-1"\n\n\nInitialisation du client
\n\nCréons un client S3 asynchrone :
\n\nuse aws_sdk_s3::Client;\nuse aws_config::load_defaults;\nuse aws_config::BehaviorVersion;\n\n#[tokio::main]\nasync fn main() {\n let config = load_defaults(BehaviorVersion::latest()).await;\n let client = Client::new(&config);\n // maintenant le client est prêt à être utilisé\n}\n\n\nTéléversement d'un fichier dans S3 (Upload)
\n\nPour téléverser des données, on utilise la méthode put_object. Les données peuvent être transmises sous forme d'octets ou depuis un flux :
use aws_sdk_s3::primitives::ByteStream;\nuse std::path::Path;\n\nasync fn upload_file(client: &Client, bucket: &str, key: &str, file_path: &str) -> Result<(), Box<dyn std::error::Error>> {\n let body = ByteStream::from_path(Path::new(file_path)).await?;\n \n client\n .put_object()\n .bucket(bucket)\n .key(key)\n .body(body)\n .send()\n .await?;\n \n println!("Fichier {} téléversé dans {}/{}", file_path, bucket, key);\n Ok(())\n}\n\n\nTéléchargement d'un fichier (Get Object)
\n\nPour récupérer un objet et le sauvegarder localement :
\n\nuse tokio::io::AsyncWriteExt;\n\nasync fn download_file(client: &Client, bucket: &str, key: &str, dest_path: &str) -> Result<(), Box<dyn std::error::Error>> {\n let response = client\n .get_object()\n .bucket(bucket)\n .key(key)\n .send()\n .await?;\n \n let mut file = tokio::fs::File::create(dest_path).await?;\n let mut stream = response.body;\n \n while let Some(bytes) = stream.try_next().await? {\n file.write_all(&bytes).await?;\n }\n \n println!("Fichier {}/{} téléchargé dans {}", bucket, key, dest_path);\n Ok(())\n}\n\n\nListe des objets dans un bucket
\n\nObtenir la liste des fichiers (clés) dans un bucket :
\n\nasync fn list_objects(client: &Client, bucket: &str) -> Result<(), Box<dyn std::error::Error>> {\n let objects = client\n .list_objects_v2()\n .bucket(bucket)\n .send()\n .await?;\n \n if let Some(contents) = objects.contents {\n for obj in contents {\n if let Some(key) = obj.key {\n println!("- {}", key);\n }\n }\n }\n Ok(())\n}\n\n\nSuppression d'un objet
\n\nasync fn delete_object(client: &Client, bucket: &str, key: &str) -> Result<(), Box<dyn std::error::Error>> {\n client\n .delete_object()\n .bucket(bucket)\n .key(key)\n .send()\n .await?;\n \n println!("Objet {}/{} supprimé", bucket, key);\n Ok(())\n}\n\n\nTravailler avec MinIO et d'autres stockages compatibles S3
\n\nPour se connecter à MinIO (émulateur S3 local) ou Yandex Object Storage, il faut redéfinir l'endp