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

如何从ASP.NET MVC控制器向Ajax请求返回多文档Zip包?

问题分析与解决方案

核心问题

  1. 前端请求格式错误:重复定义dataType,数据格式与后端参数不匹配导致请求无法命中控制器;同时错误设置响应类型,无法正确处理Zip二进制文件。
  2. 控制器潜在问题:未处理文档列表为空的情况,缺少返回值;参数绑定可能因请求格式不匹配失败。

前端代码修正

var UserId = $('#downloadDocsUserId').val();

$.ajax({
    url: "@Url.Action("DownloadMyDocuments", "Home")",
    type: 'POST',
    dataType: "blob", // 明确预期响应为二进制文件
    data: JSON.stringify({ userId: UserId }), // 传递符合后端参数的JSON结构
    processData: false, // 已手动转为JSON字符串,无需jQuery自动处理
    contentType: "application/json; charset=utf-8",
    success: function (blobData) {
        // 手动创建下载链接触发文件保存
        const url = window.URL.createObjectURL(blobData);
        const a = document.createElement('a');
        a.href = url;
        a.download = "Documents.zip";
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    },
    error: function (xhr) {
        console.log("请求错误", xhr.responseText);
    }
});

修正点:

  • 移除重复的dataType定义,设置为blob以适配Zip二进制流
  • 用JSON.stringify包装参数为标准JSON结构,确保后端能正确绑定
  • 关闭processData,避免jQuery破坏JSON字符串格式
  • 成功回调中添加二进制文件的下载逻辑,直接返回的blob无法被JSON解析,需手动触发下载

控制器代码修正

[HttpPost]
public IActionResult DownloadMyDocuments([FromBody] int userId)
{
    var myDocuments = _context.Documents.Where(x => x.UserId == userId).ToList();

    if (!myDocuments.Any())
    {
        return NotFound("未找到该用户的文档");
    }

    using (var stream = new MemoryStream())
    {
        using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
        {
            foreach (var document in myDocuments)
            {
                if (System.IO.File.Exists(document.FullPath))
                {
                    byte[] fileBytes = System.IO.File.ReadAllBytes(document.FullPath);
                    var archiveEntry = archive.CreateEntry(document.FileName, CompressionLevel.Fastest);
                    
                    using (var zipStream = archiveEntry.Open())
                    {
                        zipStream.Write(fileBytes, 0, fileBytes.Length);
                    }
                }
            }
        }

        stream.Position = 0;
        return File(stream.ToArray(), "application/zip", "Documents.zip");
    }
}

修正点:

  • 参数添加[FromBody]特性,明确从请求体JSON中绑定userId
  • 简化逻辑,直接查询文档列表(无需额外ViewModel)
  • 添加空列表判断,返回NotFound结果,避免无返回值的情况
  • 移除无用的contentType变量,最终返回固定的Zip类型MIME

可选方案(表单传参)

如果不想用JSON格式传参,可改为表单提交:

  • 前端:设置contentType: "application/x-www-form-urlencoded",data: { userId: UserId },移除JSON.stringify和processData: false
  • 控制器:移除[FromBody]特性,保持int userId即可

内容的提问来源于stack exchange,提问作者SalarianEngineer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 23:12:49