MVC Web Api + Ajax创建和下载Zip文件

汤米

我正在开发一个带有按钮的应用程序,当单击该按钮时,它将调用Web api GET方法。此方法使用System.IO.Compression获取文件并创建一个zip文件夹。这部分效果很好。我看到它创建的文件夹,并且能够打开/解压缩该文件夹及其文件。我遇到的问题是,当文件返回到浏览器并且浏览器下载文件时,出现以下错误:“压缩(压缩)文件夹'... pathToTheDownloadedFile.zip'无效。我不明白我的意思做错了,所有其他非压缩文件都可以下载并打开。

这是我的Web API GET方法:

[HttpGet]
[Route("api/OrderManager/ExtractAllDocuments/{orderNum}/{mappingId}/")]
public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
{
    try
    {
        var docPath = @"" + HttpContext.Current.Server.MapPath("MyPath");
        var files = Directory.GetFiles(docPath);
        string zipName = @"supportingdocuments_order" + orderNum + ".zip";

        FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);

        using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
        {
            foreach (var fPath in files)
            {
                if (!fPath.Contains(".zip"))
                {
                    zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
                }
            }
        }
        zipToOpen.Close();
        //At this point the directory is created and saved as it should be

        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
        var fullZipPath = docPath + zipName;

        byte[] bytes = File.ReadAllBytes(fullZipPath);

        response.Content = new ByteArrayContent(bytes);
        response.Content.Headers.ContentLength = bytes.LongLength;
        response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentDisposition.FileName = zipName;
        response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(MimeMapping.GetMimeMapping(zipName));


        return response;
    }
    catch (Exception e)
    {
        var b = e.Message;
        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
        response.ReasonPhrase = string.Format("Failed To Extract Files");
        throw new HttpResponseException(response);
    }
}

这是我的$ .ajax电话:

$.ajax({
    url: 'myApiUrl',
    method: 'GET'
}).done(function (data, status, xmlHeaderRequest) {
    var downloadLink = document.createElement('a');
    var blob = new Blob([data],
        {
            type: xmlHeaderRequest.getResponseHeader('Content-Type')
        });
    var url = window.URL || window.webkitURL;
    var downloadUrl = url.createObjectURL(blob);
    var fileName = '';

    // get the file name from the content disposition
    var disposition = xmlHeaderRequest.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, '');
        }
    }

    // Blob download logic taken from: https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE workaround for "HTML7007" and "Access Denied" error.
        window.navigator.msSaveBlob(blob, fileName);
    } else {
        if (fileName) {
            if (typeof downloadLink.download === 'undefined') {
                window.location = downloadUrl;
            } else {
                downloadLink.href = downloadUrl;
                downloadLink.download = fileName;
                document.body.appendChild(downloadLink);
                downloadLink.click();
            }
        } else {
            window.location = downloadUrl;
        }

        setTimeout(function () {
            url.revokeObjectURL(downloadUrl);
        },
            100);
    }

}).fail(function (data) {
    $.notify({
        // options
        message:
            '<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
    },
        {
            // settings
            type: 'danger',
            placement: {
                from: "top",
                align: "left"
            },
            delay: 2500,
            z_index: 10031
        });

});

我对此完全不知所措。在此先感谢您提供的任何帮助,我们将不胜感激。

汤米

因此,在搜索之后,我找到了可行的解决方案。$ .ajax不喜欢二进制数据,并且认为所有内容显然都是UTF-8文本编码。因此,我使用了XMLHttpRequest(xhr)。对于那些需要它的人,以下是c#和javascript解决方案的副本。

C#WebApi控制器:

public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
    {
        try
        {
            

            var docPath = @"" + HttpContext.Current.Server.MapPath("myPath");
            var files = Directory.GetFiles(docPath);
            string zipName = @"Supporting-Documents-Order-" + orderNum + ".zip";

            FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);

            using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
            {
                foreach (var fPath in files)
                {
                    if (!fPath.Contains(".zip"))
                    {
                        zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
                    }
                }
            }
            zipToOpen.Close();
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = new StreamContent(new FileStream(docPath + zipName, FileMode.Open, FileAccess.Read));
            response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = zipName;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");                               

            return response;
        }
        catch (Exception e)
        {
            var b = e.Message;
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
            response.ReasonPhrase = string.Format("Failed To Extract Files");
            throw new HttpResponseException(response);
        }
    }

前端JavaScript:

function extractAllDocuments() {

        let xhr = new XMLHttpRequest();

        xhr.addEventListener('readystatechange', function (e) {
            if (xhr.readyState == 2 && xhr.status == 200) {
                // Download is being started
            }
            else if (xhr.readyState == 3) {
                // Download is under progress
            }
            else if (xhr.readyState == 4) {
                //operation done

                // Create a new Blob object using the response data of the onload object
                var blob = new Blob([this.response], { type: 'application/zip' });
                //Create a link element, hide it, direct it towards the blob, and then 'click' it programatically
                let a = document.createElement("a");
                a.style = "display: none";
                document.body.appendChild(a);
                //Create a DOMString representing the blob and point the link element towards it
                let url = window.URL.createObjectURL(blob);
                a.href = url;
                // get the file name from the content disposition
                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, '');
                    }
                }
                a.download = fileName;
                //programatically click the link to trigger the download
                a.click();
               
                //Remove From Server
                $.ajax({
                    url: 'myUrl',
                    method: 'DELETE'
                }).done(function (data) {

                }).fail(function (data) {

                });
                setTimeout(function () {
                    window.URL.revokeObjectURL(url);
                }, 60 * 1000);
            } else if (xhr.status == 400){
                $.notify({
                    // options
                    message:
                        '<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
                },
                    {
                        // settings
                        type: 'danger',
                        placement: {
                            from: "top",
                            align: "left"
                        },
                        delay: 2500,
                        z_index: 10031
                    });
            }
        });

        //set the request type to post and the destination url to '/convert'
        xhr.open('GET', 'MyUrl');
        //set the reponse type to blob since that's what we're expecting back
        xhr.responseType = 'blob';
        xhr.send();

        return false;
    }

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章