Krutal Modi
Krutal Modi

Reputation: 487

How can i generate and download zip file from server in angularJs application?

My code is below:

    [System.Web.Mvc.HttpPost]
    public ActionResult DownloaZipFile([FromBody] int id)
    {
        var result = _service.GetDocuments(id);
        var downloadFileName = $"Report{id}.zip";
        var downloadFilePath = Server.MapPath($"~/Uploads/TempZipDownload/{downloadFileName}");

        if (System.IO.File.Exists(downloadFilePath))
        {
            System.IO.File.Delete(downloadFilePath);
        }

        var zip = ZipFile.Open(downloadFilePath, ZipArchiveMode.Create);

        foreach (var file in result)
        {
            zip.CreateEntryFromFile(Server.MapPath(Path.Combine("~/Uploads/TempImageDownload/" + file.Filename)), file.Filename);
        }

        zip.Dispose();
        return File(downloadFilePath, "application/zip", downloadFileName);
    }

AngularJs code from component:

vm.downloadReport = function(id) {
            service.DownloadReport(id).then(function(response) {

                var file = new Blob([response.data],
                {
                    type: 'application/zip'
                });

                if (navigator.msSaveBlob) {
                    navigator.msSaveBlob(file);
                } else {
                    var fileUrl = URL.createObjectURL(file);
                    console.log(fileUrl);
                    var a = document.createElement('a');
                    a.href = fileUrl;
                    a.download = 'ReportDownload' + id + '.zip';
                    document.body.appendChild(a);
                    a.click();
                }
            });
        }

After all code its downloading zip file but when I am trying to open zip file its giving me error. Invalid zip file.

Please note I have used System.IO.Compression libraries to generate and download zip file.

Upvotes: 0

Views: 2503

Answers (2)

ADyson
ADyson

Reputation: 61983

I think you can just do window.location.href = response.data instead of creating a dummy hyperlink. See https://developer.mozilla.org/en-US/docs/Web/API/Location for documentation.

You could also reduce the whole thing to a single HTTP request by using window.location.href to visit a single action URL (e.g. /downloadZipFile) which creates the ZIP file and then sends it for download as a FileResult immediately. You may even be able to create it in-memory without saving it to disk. Then you don't need the separate AJAX call just to get the URL of the file.

Upvotes: 0

Krutal Modi
Krutal Modi

Reputation: 487

I fixed this issue by doing following:

    [System.Web.Mvc.HttpPost]
    public ActionResult DownloaZipFile([FromBody] int id)
    {
        var result = _service.GetDocuments(id);
        var downloadFileName = $"Report{id}.zip";
        var downloadFilePath = Server.MapPath($"~/Uploads/TempZipDownload/{downloadFileName}");

        if (System.IO.File.Exists(downloadFilePath))
        {
            System.IO.File.Delete(downloadFilePath);
        }

        var zip = ZipFile.Open(downloadFilePath, ZipArchiveMode.Create);

        foreach (var file in result)
        {
            zip.CreateEntryFromFile(Server.MapPath(Path.Combine("~/Uploads/TempImageDownload/" + file.Filename)), file.Filename);
        }

        zip.Dispose();
        return Json($"/Uploads/TempZipDownload/{downloadFileName}");
    }

In the AngularJs code :

vm.downloadReport = function(id) {
            service.DownloadReport(id).then(function(response) {
                var a = document.createElement('a');
                a.href = response.data;
                a.download = 'ReportDownload';
                document.body.appendChild(a);
                a.click();
            });
        }

This will catch zipped file url in response.data and download it by javascript code. Hope this will helpful to others too.

Upvotes: 1

Related Questions