MVC Asp.net zip文件下载 - javascript

我在创建一个zip文件并将其发送到浏览器的MVC项目中有一些代码。当我在浏览器中手动输入URL时,一切正常,但是,如果单击页面中的链接进行下载,则会得到不同大小的文件,Windows无法打开该文件。

因此,如果我手动输入以下内容:
http://localhost/fms-ui/File/DownloadZipFile/?id=10&filename=DST-2015-11-14_04_04_04

我得到一个167字节的zip文件,它可以正常打开。

如果单击页面中的链接,则会得到一个180字节的文件,Windows则说该文件已损坏。匈奴

我的一项规定是我不能使用外部库。由于政治原因,我必须使用.Net Framework 4.5提供的库(静态ZipFile类)。

码:

  public FileContentResult DownloadZipFile(int id, string filename)
    {
        /*
         * 1 - get fileset info
         * 2 - get temp file name
         * 3 - create zip file under temp name
         * 4- return file
         */
        QuesterTangent.Wayside.FileServices.FileSet sInfo = new QuesterTangent.Wayside.FileServices.FileSet(id);
        string path = Path.Combine(sInfo.BasePath);

        string tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".zip");

        ZipFile.CreateFromDirectory(path, tempPath);

        byte[] fileBytes = System.IO.File.ReadAllBytes(tempPath);

        //System.IO.File.Delete(tempPath); Commented so I can compare the files

        filename = filename + ".zip";

        var cd = new System.Net.Mime.ContentDisposition
        {
            FileName = filename,
            Inline = false,
        };
        Response.AppendHeader("Content-Disposition", cd.ToString());

        return File(fileBytes, "application/zip");
    }

我已经尝试过在有和没有AppendHeader的情况下以及在各种contentTypes下进行此操作,但是它似乎不会影响结果。

这是调用控制器的JavaScript(我继承了此代码,但它可用于其他用途)。

function GetFile(url) {
//spin a wheel for friendly buffering time
var buffer = $('.MiddleRightDiv').spinBuffer();
$.ajax({
    url: url,
    type: "POST",
    cache: false,
    async: true,
    data: {},
    success: function (response, status, xhr) {
        // check for a filename
        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }

        var type = xhr.getResponseHeader('Content-Type');
        var blob = new Blob([response], { type: type });

        if (typeof window.navigator.msSaveBlob !== 'undefined') {
            // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
            window.navigator.msSaveBlob(blob, filename);
        } else {
            var URL = window.URL || window.webkitURL;
            var downloadUrl = URL.createObjectURL(blob);

            if (filename) {
                // use HTML5 a[download] attribute to specify filename
                var a = document.createElement("a");
                // safari doesn't support this yet
                if (typeof a.download === 'undefined') {
                    window.location = downloadUrl;
                } else {
                    a.href = downloadUrl;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                }
            } else {
                window.location = downloadUrl;
            }
            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
        }
    },
    complete: function (result) {
        if (typeof $('.MiddleRightDiv').spinBuffer !== 'undefined' && $.isFunction($('.MiddleRightDiv').spinBuffer)) {
            $('.MiddleRightDiv').spinBuffer("destroy");
        }
    }
});

任何输入都会有很大的帮助。我已经看过其他类似的帖子,但似乎都没有解决我遇到的核心问题。

谢谢,

丁斯代尔

参考方案

jQuery.ajax无法正确读取字节流(请参阅SO以获得许多与此相关的主题),因此我们必须使用旧的和好的XMLHttpRequest。这是重构为使用Blob的函数。在saveAs(blob,filename)是草稿的同时,还为其他浏览器提供了备用功能。

function GetFile(url) {
    if (window.navigator.msSaveBlob) {
        var req = new XMLHttpRequest();
        req.open('GET', url);
        req.responseType = 'arraybuffer';
        req.onload = function (e) {
            if (req.response) {
                var filename = 'archive.zip';
                var disposition = req.getResponseHeader('Content-Disposition');
                if (disposition && disposition.indexOf('attachment') !== -1) {
                    var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                    var matches = filenameRegex.exec(disposition);
                    if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
                }

                var type = req.getResponseHeader('Content-Type');

                var blob = new Blob([req.response], { type: type ? type : 'application/octet' });

                window.navigator.msSaveBlob(blob, filename);
            } else {
                throw 'Empty or invalid response';
            }
        }
        req.send();
    } else {
        //fallback for browsers without blob saver
        throw 'Not implemented';
    }
}

ASP.NET MVC 5自定义登录,无需脚手架,数据库优先 - c#

我对asp.net和mvc还是很陌生,所以我正在努力学习尽可能多的知识...为此,我从头开始编写博客网站,但是我对身份验证和授权有些困惑。由于我倾向于不真正使用任何脚手架的东西,所以我首先要使用数据库,所以不希望asp.net身份为我创建表。我对散列和加盐密码很酷,并对照数据库检查用户,我遇到的麻烦是将用户设置为登录状态并检查他们应该能够访问什么。我真的很想…

ASP.NET-如何更改JSON序列化的方式? - javascript

我正在使用ASP.NET通过以下查询返回Json文件:public ActionResult getTransactionTotals(int itemID) { DBEntities db = new DBEntities(); var query = from trans in db.Transactions // Linq query removed …

asp.net mvc或javascript将另一页的结果返回给方法 - c#

是否可以将另一个页面的结果返回给JavaScript方法或C#控制器操作?我有一个共享的复杂页面,该页面在我的网站上遍布使用,当前用于在C#后端的用户数据上设置单个变量。当用户完成共享的复杂页面后,我将返回引用页面。当用户在刷新或返回时将其作为url参数传递给返回的页面时,我返回的页面包含新选择的变量。我有一个新页面,我希望从我的共享复杂页面中返回该变量。但…

我可以在ID为键而不是ASP.NET MVC(C#)中的数组的情况下输出JSON吗 - javascript

因此,在ASP.NET MVC中,我有一个Controller动作,如下所示:public JsonResult People() { var people = db.People.ToList(); return Json(people); } 并在退出时将返回如下内容:[ { "ID": 1, "Name": &#…

在JavaScript中运行方法C# - javascript

打扰一下,我有这种C#asp方法。受保护的无效btnSave_Click(对象发送者,EventArgs e)有谁知道我该如何发送脚本给您?可以办到?。 javascript大神给出的解决方案 是的,那可以做到。为此,您在.aspx.cs页中创建了函数,然后单击保存按钮上的代码将其复制到函数中,然后执行以下步骤。//Call cs method from J…