Usando KGet como Biblioteca Rust
KGet es un gestor de descargas y también un motor Rust reutilizable para HTTP/HTTPS, FTP, SFTP, WebDAV, magnet links, callbacks de progreso, reanudación de descargas, proxy y verificación de checksum multi-algoritmo.
| English | Português | Español |
Instalación
[dependencies]
Kget = "1.7.0"
# Opcional: cliente torrent nativo
Kget = { version = "1.7.0", features = ["torrent-native"] }
# Opcional: API async
Kget = { version = "1.7.0", features = ["async"] }
Quick Start — API Builder (recomendada)
use kget::KgetError;
fn main() -> Result<(), KgetError> {
kget::builder("https://example.com/archivo.zip")
.output("./downloads/")
.connections(8)
.sha256("abc123def456...")
.download()?;
Ok(())
}
Métodos del Builder
kget::builder(url) retorna un DownloadBuilder. Todos los métodos son encadenables:
| Método | Descripción |
|---|---|
.output(ruta) |
Guardar en archivo o directorio |
.connections(n) |
Conexiones paralelas (modo turbo) |
.speed_limit(bps) |
Máximo de bytes/s (token bucket global) |
.proxy(url) |
URL del proxy HTTP o SOCKS5 |
.quiet(bool) |
Suprimir salida de progreso |
.sha256(hash) |
Verificar SHA-256 después de la descarga |
.sha512(hash) |
Verificar SHA-512 después de la descarga |
.sha1(hash) |
Verificar SHA-1 después de la descarga |
.md5(hash) |
Verificar MD5 después de la descarga |
.blake3(hash) |
Verificar BLAKE3 después de la descarga |
.verify_from(url) |
Descargar y analizar archivo de checksum sidecar GNU/BSD |
.header(nombre, valor) |
Agregar header HTTP |
.retry(config) |
Política de reintentos personalizada (RetryConfig) |
.range(inicio, fin) |
Solicitar rango de bytes específico |
Métodos terminales:
| Método | Retorna | Descripción |
|---|---|---|
.download() |
Result<DownloadResult, KgetError> |
Descarga a disco |
.download_to_bytes() |
Result<Vec<u8>, KgetError> |
Descarga en memoria |
.download_to_reader() |
Result<impl Read, KgetError> |
Reader de streaming |
.spawn() |
Result<(JoinHandle, Receiver<DownloadEvent>), KgetError> |
Hilo en background con canal de eventos |
.download_async() |
impl Future<…> |
API async (feature async) |
Descargas en Lote
let results = kget::batch([
"https://mirror1.example.com/archivo.iso",
"https://mirror2.example.com/otro.tar.gz",
])
.concurrency(4)
.output_dir("./downloads/")
.download_all();
for r in results {
match r.result {
Ok(d) => println!("✓ {} — {:.1} MB/s", r.url, d.avg_speed_bps / 1e6),
Err(e) => eprintln!("✗ {}: {}", r.url, e),
}
}
Canal de Eventos
use kget::{DownloadEvent, KgetError};
let (handle, rx) = kget::builder("https://example.com/grande.iso")
.connections(4)
.spawn()?;
for event in rx {
match event {
DownloadEvent::Progress { percent, speed_bps, eta_secs } => {
print!("\r{:.1}% {:.1} MB/s eta {}s", percent, speed_bps / 1e6, eta_secs.unwrap_or(0));
}
DownloadEvent::Completed { path, bytes, .. } => {
println!("\nGuardados {bytes} bytes en {path}");
}
DownloadEvent::Error(e) => eprintln!("Error: {e}"),
_ => {}
}
}
handle.join().ok();
# Ok::<(), KgetError>(())
Errores Tipados
pub enum KgetError {
Network(reqwest::Error),
Io(std::io::Error),
ChecksumMismatch { algorithm: String, expected: String, got: String },
Protocol(String),
Cancelled,
NotFound(String),
SidecarError(String),
Other(String),
}
Los errores permanentes (Cancelled, NotFound, ChecksumMismatch) nunca se reintentan.
Checksums
use kget::checksum::{compute_checksum, ChecksumAlgorithm};
let hash = compute_checksum(ChecksumAlgorithm::Blake3, std::path::Path::new("archivo.bin"))?;
println!("BLAKE3: {hash}");
# Ok::<(), Box<dyn std::error::Error>>(())
Algoritmos soportados: Sha256, Sha512, Sha1, Md5, Blake3.
Verificación por archivo sidecar:
kget::builder("https://example.com/release.tar.gz")
.verify_from("https://example.com/release.tar.gz.sha256sum")
.download()?;
# Ok::<(), kget::KgetError>(())
ResumePolicy
use kget::{AdvancedDownloader, ResumePolicy, Optimizer, ProxyConfig};
let mut dl = AdvancedDownloader::new(
"https://example.com/imagen.iso".to_string(),
"imagen.iso".to_string(),
true,
ProxyConfig::default(),
Optimizer::new(),
)?;
dl.set_resume_policy(ResumePolicy::AlwaysResume); // nunca bloquea en stdin
dl.download()?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
| Variante | Comportamiento |
|---|---|
Ask (defecto) |
Solicita via stdin en sesiones interactivas |
AlwaysResume |
Ignora el prompt, procede sin preguntar |
AlwaysRestart |
Ignora el prompt, reinicia desde cero |
Los llamadores de la biblioteca siempre deben establecer AlwaysResume o AlwaysRestart.
Descarga HTTP Avanzada Paralela
use kget::{AdvancedDownloader, Optimizer, ProxyConfig};
let mut downloader = AdvancedDownloader::new(
"https://example.com/grande.iso".to_string(),
"grande.iso".to_string(),
false,
ProxyConfig::default(),
Optimizer::new(),
)?; // new() retorna Result — propaga con ?
downloader.set_resume_policy(kget::ResumePolicy::AlwaysResume);
downloader.set_progress_callback(|progress| {
print!("\r{:.1}%", progress * 100.0);
});
downloader.download()?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
Descarga HTTP Simple
use kget::{download, DownloadOptions, Optimizer, ProxyConfig};
let options = DownloadOptions {
output_path: Some("archivo.zip".to_string()),
..Default::default()
};
download(
"https://example.com/archivo.zip",
ProxyConfig::default(),
Optimizer::new(),
options,
None,
)?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
Descarga en Memoria
let bytes: Vec<u8> = kget::builder("https://example.com/datos.json")
.download_to_bytes()?;
println!("Recibidos {} bytes", bytes.len());
# Ok::<(), kget::KgetError>(())
FTP
use kget::ftp::FtpDownloader;
use kget::{Optimizer, ProxyConfig};
let dl = FtpDownloader::new(
"ftp://ftp.gnu.org/gnu/emacs/emacs-28.2.tar.gz".to_string(),
"emacs-28.2.tar.gz".to_string(),
false,
ProxyConfig::default(),
Optimizer::new(),
);
dl.download()?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
SFTP
use kget::sftp::SftpDownloader;
use kget::{Optimizer, ProxyConfig};
let dl = SftpDownloader::new(
"sftp://usuario:clave@servidor.example.com/ruta/archivo.tar.gz".to_string(),
"archivo.tar.gz".to_string(),
false,
ProxyConfig::default(),
Optimizer::new(),
);
dl.download()?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
Prioridad de autenticación:
- Contraseña en la URL (
sftp://usuario:clave@host/ruta) - SSH agent activo
- Archivos de clave por defecto (
~/.ssh/id_ed25519,~/.ssh/id_rsa,~/.ssh/id_ecdsa)
Las host keys se verifican contra ~/.ssh/known_hosts; las divergencias generan error.
WebDAV
use kget::webdav::WebDavDownloader;
use kget::{Optimizer, ProxyConfig};
let dl = WebDavDownloader::new(
"webdavs://usuario:clave@nas.local/backups/db.tar.gz".to_string(),
"db.tar.gz".to_string(),
false,
ProxyConfig::default(),
Optimizer::new(),
);
dl.download()?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
yt-dlp
use kget::ytdlp::{download_video, VideoQuality, is_video_url};
if is_video_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ") {
download_video(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
VideoQuality::Quality720p,
"./downloads",
None,
)?;
}
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
Magnet Links
use kget::{download_magnet, Optimizer, ProxyConfig, TorrentCallbacks};
use std::sync::Arc;
download_magnet(
"magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567",
"./downloads",
true,
ProxyConfig::default(),
Optimizer::new(),
TorrentCallbacks {
status: Some(Arc::new(|msg| println!("{msg}"))),
progress: Some(Arc::new(|p| println!("{:.1}%", p * 100.0))),
},
)?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
Metalink
use kget::metalink::download_metalink;
use kget::{Optimizer, ProxyConfig};
download_metalink(
"ubuntu-24.04.meta4",
"~/Downloads",
false,
ProxyConfig::default(),
Optimizer::new(),
)?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
Historial de Descargas
use kget::queue::{DownloadHistory, EntryStatus, HistoryEntry};
let mut history = DownloadHistory::load();
let entry = HistoryEntry::new("https://example.com/archivo.iso", "/home/user/Downloads", None);
history.record(entry, EntryStatus::Completed, None);
history.save()?;
for e in history.recent(10) {
println!("{} {} {}", e.created_at_display(), e.status, e.filename);
}
history.clear_completed();
history.save()?;
# Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
API Async
Con --features async:
#[tokio::main]
async fn main() -> Result<(), kget::KgetError> {
kget::builder("https://example.com/archivo.zip")
.output("./downloads/")
.connections(4)
.download_async()
.await?;
Ok(())
}
Garantías de la Biblioteca
- Los llamadores de la biblioteca nunca bloquean en
stdincuandoResumePolicyestá configurada. - Progreso y estado se exponen via callbacks y canales de eventos.
- Los archivos se transmiten a disco (excepto
.download_to_bytes()). - Los nombres de archivo se validan: rechaza bytes nulos, path traversal, >255 bytes y nombres reservados de Windows.
- Solo los errores 5xx y de conexión se reintentan; los 4xx fallan inmediatamente.
Ver examples/lib_usage.rs para más ejemplos.