如何将包含多个文档的 zip 文件从 ASP.NET MVC 控制器返回到 Ajax 请求?

问题描述 投票:0回答:1

我正在尝试从文件系统中压缩一些文件,然后通过前端的 Ajax 请求返回该文件。

我的文档模型包含有关文件所在位置的所有信息以及名称,因此

document.FullPath
是文件的完全限定名称 (
path\filename.extension
)。

我目前遇到错误

内容类型不正确:application/json

我不明白为什么。它不会影响控制器动作。

我的控制器看起来像这样:

    [HttpPost]
    public IActionResult DownloadMyDocuments(int userId)
    {
        DocumentViewModel documentViewModel= new();
        
        documentViewModel.MyDocuments = _context.Documents.Where(x => x.UserId.Equals(userId)).ToList();

        string contentType = null; 

        if (documentViewModel.MyDocuments != null)
        {
            using (var stream = new MemoryStream())
            {
                using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
                {
                    foreach (MyDocument document in documentViewModel.MyDocuments)
                    {
                        if (System.IO.File.Exists(document.FullPath))
                        {
                            contentType = FileHelper.GetMimeContentType(document.FullPath);

                            byte[] file = System.IO.File.ReadAllBytes(document.FullPath);

                            var archiveEntry = archive.CreateEntry(document.FileName, CompressionLevel.Fastest);

                            using (var zipStream = archiveEntry.Open())
                            {
                                zipStream.Write(file, 0, file.Length);
                            }
                        }
                    }
                }

                stream.Position = 0;

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

我在前端的请求如下所示:

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

$.ajax({
    url: "@Url.Action("DownloadMyDocuments", "Home")",
    type: 'POST',
    dataType: "JSON",
    data: UserId,
    processData: true,
    dataType: "application/zip",
    contentType: "application/json; charset=utf-8",
    success: function (data) {
        console.log("success", data);
    },
    error: function (data) {
        console.log("error", data);
    }
});
c# jquery .net ajax asp.net-core-mvc
1个回答
0
投票

DataType 用于告诉 jQuery 它期望从服务器接收的数据类型,而不是指定发送到服务器的数据类型。对于文件下载,实际上不需要指定 dataType,因为需要二进制数据(文件),而不是 JSON 或其他数据格式。您可以创建一个Blob对象,指定该对象的MIME类型为“application/zip”,表明它是一个ZIP文件,并使用JavaScript动态创建下载链接。下载完成后,链接元素将从文档中删除。以保持页面清晰度。这是一个示例代码,您可以参考:

    <h2>Download My Documents</h2>

<button id="downloadButton">Download </button>

@section scripts {
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
    <script>
        $(document).ready(function () {
            $("#downloadButton").click(function () {
                var userId = 123;
                $.ajax({
                    url: "@Url.Action("DownloadMyDocuments", "Download")" + "?userId=" + userId,
                    type: 'POST',  
                    xhrFields: {
                        responseType: 'blob'  
                    },
                    success: function (data) {
                        var myCustomBlob = new Blob([data], { type: "application/zip" });
                        var link = document.createElement('a');
                        link.href = window.URL.createObjectURL(myCustomBlob);
                        link.download = "Documents.zip";
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                    },
                    error: function (xhr, status, error) {
                        console.log("Error:", error);
                    }
                });
            });
        });

    </script>
}

我的控制器:

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

     using (var stream = new MemoryStream())
     {
         using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
         {
             foreach (var document in documents)
             {
                 if (System.IO.File.Exists(document.FullPath))
                 {
                     byte[] file = System.IO.File.ReadAllBytes(document.FullPath);
                     var archiveEntry = archive.CreateEntry(document.FileName, CompressionLevel.Fastest);

                     using (var zipStream = archiveEntry.Open())
                     {
                         zipStream.Write(file, 0, file.Length);
                     }
                 }
             }
         }

         stream.Position = 0;

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

当我点击按钮时:

将会下载对应的文件:

© www.soinside.com 2019 - 2024. All rights reserved.