Dateien senden

Salvo bietet mehrere Möglichkeiten zum Versenden von Dateien:

NamedFile

Salvo stellt salvo::fs::NamedFile bereit, um Dateien effizient an Clients zu senden. Dabei werden die Dateien nicht vollständig in den Cache geladen, sondern basierend auf dem Range-Header der Anfrage nur teilweise übertragen.

Tatsächlich ist Response::send_file nur eine vereinfachte Methode zur Verwendung von NamedFile. Für erweiterte Kontrolle über den Dateiversand kann NamedFileBuilder genutzt werden.

Mit NamedFile::builder lässt sich ein NamedFileBuilder erstellen:

#[handler]
async fn send_file(req: &mut Request, res: &mut Response) {
    let builder = NamedFile::builder("/file/to/path");
}

Nach Konfiguration kann die Datei gesendet werden:

#[handler]
async fn send_file(req: &mut Request, res: &mut Response) {
    NamedFile::builder("/file/to/path").attached_name("image.png").send(req.headers(), res).await;
}

Statische Dateien bereitstellen

Middleware zum Bereitstellen statischer oder eingebetteter Dateien.

  • StaticDir unterstützt statische lokale Verzeichnisse. Es können mehrere Ordnerpfade übergeben werden, z.B.:
main.rs
Cargo.toml
static-dir-list/src/main.rs
use salvo::prelude::*;
use salvo::serve_static::StaticDir;

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();

    let router = Router::with_path("{*path}").get(
        StaticDir::new([
            "static-dir-list/static/boy",
            "static-dir-list/static/girl",
            "static/boy",
            "static/girl",
        ])
        .include_dot_files(false)
        .defaults("index.html")
        .auto_list(true),
    );

    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

Falls eine Datei im ersten Ordner nicht gefunden wird, wird im zweiten gesucht.

  • Unterstützung für rust-embed ist vorhanden, z.B.:
main.rs
Cargo.toml
static-embed-files/src/main.rs
use rust_embed::RustEmbed;
use salvo::prelude::*;
use salvo::serve_static::static_embed;

#[derive(RustEmbed)]
#[folder = "static"]
struct Assets;

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();

    let router = Router::with_path("{*path}").get(static_embed::<Assets>().fallback("index.html"));

    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

Mit with_fallback kann eine Ersatzdatei für den Fall definiert werden, dass die angeforderte Datei nicht existiert - besonders nützlich für Single-Page-Webanwendungen.