基于Axum实现点击按钮生成服务器文件并本地下载的技术问询
实现步骤指导
1. 生成带下载按钮的HTML页面
把原check_files函数改为返回HTML页面,让用户能直观看到两个下载按钮,按钮点击后跳转至专门的下载接口:
use axum::response::Html; // 保留原有其他引入 async fn check_files(Path(run_number): Path<u32>) -> Html<String> { let html = format!( r#" <html> <body> <h1>Download Files for Run {run_number}</h1> <button onclick="location.href='/download/csv/{run_number}'">Download csv</button> <button onclick="location.href='/download/txt/{run_number}'">Download txt</button> </body> </html> "# ); Html(html) }
2. 添加下载处理路由
在main函数中新增下载相关路由,分别对应csv和txt文件的下载请求:
#[tokio::main] async fn main() { let app = Router::new() .route("/", get(|| async { "Hello, World!" })) .route("/:run_number", get(check_files)) // 新增下载路由 .route("/download/csv/:run_number", get(download_csv)) .route("/download/txt/:run_number", get(download_txt)); let listener = tokio::net::TcpListener::bind("127.0.0.1:8080") .await .unwrap(); axum::serve(listener, app).await.unwrap(); }
3. 实现核心下载逻辑
编写通用处理函数,完成文件存在性检查、外部命令生成文件、返回下载响应三个核心步骤:
use axum::response::{NamedFile, IntoResponse}; use tokio::process::Command; use std::path::Path; // 通用下载处理,接受文件后缀参数 async fn download_file(run_number: u32, ext: &str) -> Result<impl IntoResponse, String> { let file_path = format!("{run_number}.{ext}"); let path = Path::new(&file_path); // 文件不存在则执行外部命令生成 if !path.exists() { let status = Command::new("touch") .arg(&file_path) .status() .await .map_err(|e| format!("执行生成命令失败: {}", e))?; if !status.success() { return Err(format!("命令执行失败,状态码: {}", status)); } } // 返回文件下载,设置响应头触发浏览器下载行为 NamedFile::open(path) .await .map(|file| file.with_header(("Content-Disposition", format!("attachment; filename=\"{file_path}\"")))) .map_err(|e| format!("打开文件失败: {}", e)) } // 封装csv文件下载处理 async fn download_csv(Path(run_number): Path<u32>) -> impl IntoResponse { download_file(run_number, "csv").await } // 封装txt文件下载处理 async fn download_txt(Path(run_number): Path<u32>) -> impl IntoResponse { download_file(run_number, "txt").await }
4. 补充依赖配置
确保Cargo.toml中包含所需依赖:
[dependencies] axum = "0.7" tokio = { version = "1.0", features = ["full"] }
关键注意事项
- 异步命令执行:必须使用
tokio::process::Command而非std::process::Command,避免阻塞Axum的事件循环影响服务性能。 - 错误处理:示例用简单字符串返回错误,实际项目可结合Axum的
StatusCode和自定义错误类型优化用户体验。 - 安全防护:若服务需暴露公网,要验证
run_number的合法性,防止路径遍历或恶意命令执行风险。
内容的提问来源于stack exchange,提问作者DJDuque
相关产品推荐
相关产品推荐

