MVC Asp.net zip文件下载 [英] MVC Asp.net zip file download

查看:66
本文介绍了MVC Asp.net zip文件下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have some code in an MVC project that creates a zip file and sends it to the browser. Everything works when I manually enter the URL in the browser, but if I click on the link in the page to get the download, I get a file of a different size and Windows cannot open it.

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

So, if I manually enter something like this: http://localhost/fms-ui/File/DownloadZipFile/?id=10&filename=DST-2015-11-14_04_04_04

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

I get a zip file of 167 bytes and it open fine.

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

If I click on the link in the page, I get a file of 180 bytes and Windows says the file is corrupted. Hun?

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

My one stipulation is that I cannot use an external library. Due to politics I must use the library provided with .Net Framework 4.5 (static ZipFile class).

代码:

  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和不使用AppendHeader以及使用各种contentTypes的情况,但是它似乎不会影响结果.

I've tried this with and without AppendHeader and with various contentTypes, but it doesn't seem to effect the outcome.

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

Here is the JavaScript that calls the controller (I inherited this code but it works for other things).

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");
        }
    }
});

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

Any input would be a great help. I have gone over other similar postings but non of them seems to address the core problem I am having.

谢谢

dinsdale

推荐答案

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

jQuery.ajax cannot read bytestreams correctly (check SO for many topics about this), so we have to use old and good XMLHttpRequest. Here is your function refactored to work with blobs. Extened it with fallbacks for other browsers while saveAs(blob,filename) is the draft.

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

这篇关于MVC Asp.net zip文件下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆