【问题标题】:MVC Asp.net zip file downloadMVC Asp.net zip 文件下载
【发布时间】:2015-11-21 04:03:45
【问题描述】:

我在一个 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");
        }
    }
});

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

谢谢,

丁斯代尔

【问题讨论】:

  • 尝试将ajax方法从“POST”改为“GET”(或者去掉类型定义,GET是默认的)
  • 没有区别。当字节数组被读入控制器上的内存时,它是 167 个字节。当它到达 IE 时,它的 180 个字节无法打开。发生了什么可能会在我的文件中添加 13 个字节?

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


【解决方案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';
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多