MVC Asp.net压缩文件下载

时间:2015-11-21 04:03:46

标签: javascript c# asp.net asp.net-mvc

我在MVC项目中有一些代码,它创建一个zip文件并将其发送到浏览器。当我在浏览器中手动输入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");
        }
    }
});

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

谢谢,

dinsdale

1 个答案:

答案 0 :(得分:1)

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';
    }
}