Rust Actix服务端返回Zip文件,前端TypeScript下载报错求助
问题:Actix服务端返回Zip文件,Axios客户端无法正常下载解析
服务端代码(Rust Actix)
pub async fn download_project( _req: HttpRequest, form: web::Json<DownloadProj> ) -> actix_web::Result<impl actix_web::Responder> { let zip_path = handle_compress_proj(&form.0); match NamedFile::open(&zip_path) { Ok(fe) => { // Ok(NamedFile::into_response(fe, &req)) Ok( fe.use_last_modified(true) ) }, Err(_) => Err(actix_web::error::ErrorBadRequest("File not Found") ) } }
服务端返回Zip文件的二进制数据(浏览器显示为PK开头的乱码)。
客户端代码(TypeScript + Axios)
下载请求函数
export function downloadProj(req: QueryDownload) { const config: AxiosRequestConfig = { method: 'put', url: '/tex/project/download', data: JSON.stringify(req) }; const actionTypeString: string = ProjectActionType[ProjectActionType.DOWNLOAD_PROJ]; return XHRClient.requestWithActionType(config, actionTypeString, store); }
下载处理函数
const handleProjDownload = (docItem: TexProjectModel) => { let proj : QueryDownload = { project_id: docItem.project_id, version: "1" }; downloadProj(proj).then((resp) => { debugger const url = window.URL.createObjectURL(resp); const link = document.createElement('a'); link.href = url; link.download = 'file.zip'; link.click(); window.URL.revokeObjectURL(url); }); }
遇到的问题
- 调用
window.URL.createObjectURL(resp)时触发错误:ProjectTab.tsx:74 Uncaught (in promise) TypeError: Failed to execute 'createObjectURL' on 'URL': Overload resolution failed. - 尝试调用
resp.blob()时触发错误:Uncaught (in promise) TypeError: resp.blob is not a function - 手动创建Blob后生成的Zip文件无法打开
- 使用curl命令可正常下载:
curl -H "Content-Type: application/json" -X PUT -d '{"project_id": "5ef2057551c24b5aa4d0e2cdadcbc524","version": "1"}' -H "Authorization: Bearer eyJhbxxxxx" -o filename1.zip https://tex.example.top/tex/project/download
解决方案
1. 配置Axios响应类型为Blob
Axios默认会将响应解析为JSON,导致二进制Zip数据被破坏。需要在请求配置中添加responseType: 'blob',让Axios直接返回Blob类型的二进制数据:
export function downloadProj(req: QueryDownload) { const config: AxiosRequestConfig = { method: 'put', url: '/tex/project/download', data: JSON.stringify(req), responseType: 'blob' // 新增配置 }; const actionTypeString: string = ProjectActionType[ProjectActionType.DOWNLOAD_PROJ]; return XHRClient.requestWithActionType(config, actionTypeString, store); }
2. 正确处理Blob响应
修改下载处理函数,确保接收的响应是Blob类型,再创建ObjectURL:
const handleProjDownload = (docItem: TexProjectModel) => { let proj : QueryDownload = { project_id: docItem.project_id, version: "1" }; downloadProj(proj).then((resp: Blob) => { const url = window.URL.createObjectURL(resp); const link = document.createElement('a'); link.href = url; link.download = 'file.zip'; link.click(); window.URL.revokeObjectURL(url); }); }
3. 服务端可选优化(确保响应头正确)
虽然curl能正常下载,但可以给Actix的响应添加明确的Content-Type和Content-Disposition头,帮助浏览器更好识别文件类型:
pub async fn download_project( req: HttpRequest, form: web::Json<DownloadProj> ) -> actix_web::Result<impl actix_web::Responder> { let zip_path = handle_compress_proj(&form.0); match NamedFile::open(&zip_path) { Ok(mut fe) => { Ok(fe .use_last_modified(true) .set_content_type("application/zip") .set_disposition( actix_web::http::header::ContentDisposition::attachment() .filename("file.zip") .unwrap() )) }, Err(_) => Err(actix_web::error::ErrorBadRequest("File not Found") ) } }
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

