You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:47:12