206 lines
5.4 KiB
Markdown
206 lines
5.4 KiB
Markdown
# Exemples du module Download
|
|
|
|
Ce répertoire contient des exemples d'utilisation du module `download` de pmocache.
|
|
|
|
## Fichiers
|
|
|
|
### `test_download.rs`
|
|
Exemple basique de téléchargement sans transformation.
|
|
|
|
**Utilisation:**
|
|
```bash
|
|
cargo run --example test_download
|
|
```
|
|
|
|
### `test_download_transformer.rs`
|
|
Exemples complets de transformers :
|
|
- Transformation en majuscules
|
|
- Suppression de header (skip N bytes)
|
|
- Numérotation des lignes
|
|
- Compression GZIP (commenté, nécessite async-compression)
|
|
|
|
**Utilisation:**
|
|
```bash
|
|
cargo run --example test_download_transformer
|
|
```
|
|
|
|
### `simple_transformer.rs`
|
|
Exemple de documentation montrant la syntaxe et l'API.
|
|
|
|
**Utilisation:**
|
|
```bash
|
|
cargo run --example simple_transformer
|
|
```
|
|
|
|
## Concepts clés
|
|
|
|
### 1. Téléchargement simple
|
|
|
|
```rust
|
|
use pmocache::download::download;
|
|
|
|
let dl = download("/tmp/file.dat", "https://example.com/file.dat");
|
|
dl.wait_until_finished().await?;
|
|
```
|
|
|
|
### 2. Téléchargement avec transformer
|
|
|
|
Un transformer est une fonction qui :
|
|
1. Reçoit le stream de réponse HTTP
|
|
2. Reçoit un fichier ouvert en écriture
|
|
3. Reçoit un callback de progression
|
|
4. Traite les données à la volée
|
|
5. Écrit le résultat transformé dans le fichier
|
|
|
|
```rust
|
|
let transformer: StreamTransformer = Box::new(|response, mut file, update_progress| {
|
|
Box::pin(async move {
|
|
let mut stream = response.bytes_stream();
|
|
let mut total = 0u64;
|
|
|
|
while let Some(chunk_result) = stream.next().await {
|
|
let chunk = chunk_result.map_err(|e| e.to_string())?;
|
|
|
|
// Transformer les données
|
|
let transformed = your_transformation(&chunk);
|
|
|
|
// Écrire le résultat
|
|
file.write_all(&transformed).await.map_err(|e| e.to_string())?;
|
|
|
|
// Mettre à jour la progression
|
|
total += transformed.len() as u64;
|
|
update_progress(total);
|
|
}
|
|
|
|
file.flush().await.map_err(|e| e.to_string())?;
|
|
Ok(())
|
|
})
|
|
});
|
|
|
|
let dl = download_with_transformer("/tmp/output.dat", "https://example.com/input.dat", Some(transformer));
|
|
```
|
|
|
|
### 3. Suivi de progression
|
|
|
|
```rust
|
|
let dl = download("/tmp/file.dat", "https://example.com/file.dat");
|
|
|
|
// Attendre au moins 1MB
|
|
dl.wait_until_min_size(1024 * 1024).await?;
|
|
println!("Au moins 1MB téléchargés");
|
|
|
|
// Voir la progression
|
|
loop {
|
|
let current = dl.current_size().await;
|
|
let expected = dl.expected_size().await;
|
|
|
|
if let Some(total) = expected {
|
|
println!("Progression: {}/{} bytes ({:.1}%)",
|
|
current, total, 100.0 * current as f64 / total as f64);
|
|
} else {
|
|
println!("Téléchargés: {} bytes", current);
|
|
}
|
|
|
|
if dl.finished().await {
|
|
break;
|
|
}
|
|
|
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
}
|
|
```
|
|
|
|
## Cas d'usage pour PMOMusic
|
|
|
|
### Conversion d'images pour le cache
|
|
|
|
```rust
|
|
// Télécharger une couverture d'album et la convertir en WebP
|
|
fn webp_transformer() -> StreamTransformer {
|
|
Box::new(|response, mut file, update_progress| {
|
|
Box::pin(async move {
|
|
let bytes = response.bytes().await.map_err(|e| e.to_string())?;
|
|
let img = image::load_from_memory(&bytes)
|
|
.map_err(|e| format!("Decode error: {}", e))?;
|
|
|
|
let encoder = webp::Encoder::from_image(&img)
|
|
.map_err(|e| format!("Encode error: {}", e))?;
|
|
let webp = encoder.encode(75.0);
|
|
|
|
file.write_all(&*webp).await.map_err(|e| e.to_string())?;
|
|
file.flush().await.map_err(|e| e.to_string())?;
|
|
|
|
update_progress(webp.len() as u64);
|
|
Ok(())
|
|
})
|
|
})
|
|
}
|
|
|
|
// Utilisation dans pmocovers
|
|
let transformer = webp_transformer();
|
|
let dl = download_with_transformer(cache_path, cover_url, Some(transformer));
|
|
```
|
|
|
|
### Conversion audio pour le cache
|
|
|
|
```rust
|
|
// Télécharger du MP3 et le convertir en FLAC
|
|
fn mp3_to_flac_transformer() -> StreamTransformer {
|
|
Box::new(|response, mut file, update_progress| {
|
|
Box::pin(async move {
|
|
let mp3_bytes = response.bytes().await.map_err(|e| e.to_string())?;
|
|
|
|
// Décoder MP3
|
|
let decoded = decode_mp3(&mp3_bytes)?;
|
|
|
|
// Encoder FLAC
|
|
let flac_bytes = encode_flac(&decoded)?;
|
|
|
|
file.write_all(&flac_bytes).await.map_err(|e| e.to_string())?;
|
|
file.flush().await.map_err(|e| e.to_string())?;
|
|
|
|
update_progress(flac_bytes.len() as u64);
|
|
Ok(())
|
|
})
|
|
})
|
|
}
|
|
|
|
// Utilisation dans pmoaudiocache
|
|
let transformer = mp3_to_flac_transformer();
|
|
let dl = download_with_transformer(cache_path, audio_url, Some(transformer));
|
|
```
|
|
|
|
### Streaming progressif
|
|
|
|
```rust
|
|
// Commencer à lire pendant le téléchargement
|
|
let dl = download(audio_path, stream_url);
|
|
|
|
// Attendre le buffer minimal (256KB)
|
|
dl.wait_until_min_size(256 * 1024).await?;
|
|
|
|
// Ouvrir et commencer à lire
|
|
let mut file = dl.open()?;
|
|
let mut buffer = [0u8; 4096];
|
|
|
|
loop {
|
|
// Lire ce qui est disponible
|
|
match file.read(&mut buffer) {
|
|
Ok(0) if dl.finished().await => break, // EOF
|
|
Ok(0) => {
|
|
// Pas encore de données, attendre un peu
|
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
|
}
|
|
Ok(n) => {
|
|
// Traiter les données lues
|
|
process_audio_chunk(&buffer[..n]);
|
|
}
|
|
Err(e) => return Err(e.into()),
|
|
}
|
|
}
|
|
```
|
|
|
|
## Voir aussi
|
|
|
|
- [DOWNLOAD_MODULE.md](../DOWNLOAD_MODULE.md) - Documentation complète du module
|
|
- [src/download.rs](../src/download.rs) - Code source
|