【问题标题】:File Download Link from API functionAPI函数的文件下载链接
【发布时间】:2022-08-18 00:59:15
【问题描述】:

我有一个充当代理的 Rust 控制台应用程序。从用户的角度来看,有一个 Web UI 前端。这包含一个按钮,当被调用时将触发对 rust 服务的 GET 请求。这又会调用一个返回 CSV 文件的外部端点。

我想要做的是当用户单击按钮时将文件下载到浏览器。现在我将 CSV 文件的内容返回到浏览器而不是文件本身。

当用户单击按钮时,它将请求路由到下载文件防锈功能...

    pub async fn serve(listen_addr: SocketAddr) {
    tokio::spawn(license::load());

    let detectservices = Router::new()
        .route(\"/downloadfile\", get(detectservices::downloadfile));

    serve_message_apis().await;

    info!(\"API server listening on {listen_addr}\");

    Server::bind(&listen_addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

将调用外部端点(本例中为 docker 容器)并返回文件的 downloadfile 函数

pub async fn downloadfile() -> Result<Json<String>, ApiError> {
    
    println!(\"downloadfile\");
   
    let endpoint = \"http://127.0.0.1:7453/api/CSV/DownloadFile\";
    let filename = \"local_jg_1-doc_637958283544997211.csv\".to_owned();

    let mut path = String::new();

    path += &endpoint;
    path += \"?filename=\";
    path += &filename;

    println!(\"endpoint = {} filename = {}\", endpoint, filename);
    println!(\"path = {}\", path);

    let response = reqwest::get(path).await?;

    let tmp_dir = Builder::new().prefix(\"example\").tempdir()?;

    let mut dest = {
        let fname = response
            .url()
            .path_segments()
            .and_then(|segments| segments.last())
            .and_then(|name| if name.is_empty() { None } else { Some(name) })
            .unwrap_or(\"tmp.csv\");

        println!(\"file to download: \'{}\'\", fname);
        let fname = tmp_dir.path().join(fname);
        println!(\"will be located under: \'{:?}\'\", fname);
        File::create(fname)?
    };

    println!(\"dest {:?}\", dest);

    let content =  response.text().await?;

    println!(\"content {:?}\", content);
    copy(&mut content.as_bytes(), &mut dest)?;
    
    Ok(Json(content))
}

我理解我获取内容的原因是因为我将内容字符串作为 JSON 返回 - 这是有道理的 - 但是我需要更改什么来返回文件本身以便浏览器直接为用户下载它?

标签: rust


【解决方案1】:

我已经设法解决它,它现在通过 GET 请求返回文件 - 我仍在努力添加动态头文件名,但对于另一个问题 - 有效的功能如下

use axum::extract::Json;
    use crate::detectservices::header::HeaderName;
    use axum::http::{header};
    use axum::response::{Headers, IntoResponse};
    
    use axum::{
        extract::Query,
    };
    
    pub async fn downloadfile(query_string: Query<DownloadQueryString>) -> Result<(Headers<[(HeaderName, &'static str); 2]>, String), ApiError> {
        
        println!("downloadfile - the query_string was {}", query_string.filename);
        
        let endpoint = "http://127.0.0.1:6101/api/CSV/DownloadFile";
    
        let mut csv_file_name = String::new();
    
        csv_file_name += &query_string.filename;
    
        let mut path = String::new();
    
        path += &endpoint;
        path += "?filename=";
        path += &csv_file_name;
    
        println!("endpoint = {} filename = {}", endpoint, csv_file_name);
        println!("path = {}", path);
    
        let response = reqwest::get(path).await?;
    
        let content =  response.text().await?;
    
        let headers = Headers([
            (header::CONTENT_TYPE, "text/csv; charset=utf-8"),
                (
                    header::CONTENT_DISPOSITION,
                    "attachment; filename=\"data.csv\"",
                ),
        ]);
        
        Ok((headers, content))
    
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多