0

I have an MVC application which i am trying to give the user the opportunity to download a zip of files,but unsuccesfully.Let me explain further.

Inside my view(ImageViewer.cshtml) i have a div class with an on click event that when pressed i call the controller method(ImageViewerController.GetZipPhotos) which handles the download of the zip file.See below:

div class="text" onclick="GetZipPhotos()">Download</div> 

and the Javascript that get called is this:

function GetZipPhotos() {   
        $.ajax({
                url: '@Url.Action("GetZipPhotos", "ImageViewer",Request.Url.Scheme)',
                type: 'POST',
                contentType: 'application/zip',
                error: function () {
                        alert('There was an error!'+result);
                        }
              });                     
    }

Now, inside my ImageViewerController i have the following method:

[HttpPost]
    public ActionResult GetZipPhotos()
    {
        ZipResult newZipResult=new ZipResult(
            Server.MapPath("~/File1.txt"),
            Server.MapPath("~/File2.txt")
            );
        newZipResult.OutPutZipFileName = "PhotosZip.zip";
        return newZipResult;
    }

and the declaration of the ZipResult custom action is:

public class ZipResult:ActionResult
{
    private IEnumerable<string> _filesToZip;
    private string _outPutZipFileName="ZipFile.zip";        

    public ZipResult(params string[] filesToZip)
    {
        this._filesToZip = filesToZip;
    }        

    public override void ExecuteResult(ControllerContext context)
    {                                       
       using (ZipFile oneZipFile = new ZipFile()) {
           oneZipFile.AddFiles(_filesToZip);
           context.HttpContext.Response.ContentType = "application/zip";
           context.HttpContext.Response.AppendHeader("content-disposition", "attachment; filename=" + _outPutZipFileName);
           oneZipFile.Save(context.HttpContext.Response.OutputStream);
       }            
    }
}

The problem is that the code ofcourse doesn't work because the name of the view that called the controller is different from the actual method(GetZipPhotos).The view's name is ImageViewer.cshtml and the controller's name is ImageViewerController. As fas as i have understood, the MVC framework uses code conventions, so it expects the name of the method to be the same as the view.The problem is that my view and the method are diferrent so the response never gets to back to the view. I thought of creating a new view that has basically nothing inside, just to call it from the method and return the zip file.If this could be a possible solution, how can i tell from the action result which view to send the response?

3
  • 1
    How do you know this is not working? I don't see you're doing anything with the result of the ajax call, the zip file. You don't need to make it an ajax call, btw. Simple link to ImageViewer/GetZipPhotos should do what you want. Also, you probably want to use built-in FileResult and make the zip file in that action. Commented Oct 21, 2014 at 14:20
  • 1
    1) There's no view involved here. You're returning a fully formed result. 2) You can't just request a zip file via AJAX. You might be able to use the HTML5 File API to read in the returned data from the AJAX call to create a file locally and then prompt the user to download that. But, you have to handle all that; the browser won't by default. 3) As @Floremin said, there's no reason to use AJAX anyways. Just link directly to this action. Commented Oct 21, 2014 at 14:28
  • I tried to implement the solution from the following article: campusmvp.net/blog/… Floremin i will try out your tips. Chris the solution you are suggesting although could definitely could work seems a bit daunting at this moment. Commented Oct 21, 2014 at 14:34

2 Answers 2

1

No need to use ajax for the file download. The browser will normally start the download and keep you on the same page. Also, no need for a custom action result, you can just use FileResult. Try something like this:

public FileResult GetZipPhotos()
{
    var filesToZip = new List<string> { Server.MapPath("~/File1.txt"), Server.MapPath("~/File2.txt") };

    var oneZipFile = new ZipFile();
    oneZipFile.AddFiles(filesToZip);

    return File(oneZipFile.ToByteArray(), "application/zip", "PhotosZip.zip");
}

Of course, you'll need to figure out this part oneZipFile.ToByteArray(), but the ZipFile class probably already has something like that.

Sign up to request clarification or add additional context in comments.

1 Comment

Floremin the ajax call was the origin of my problem.I switched to a @Html.ActionLink and it worked.I dont have to change anything else,just this.
1

Your ajax call is redirecting the response into nowhere.

I would do it like this:

use a hidden iframe, change its src to the desired path in your function and it should be prompting a file dialog.

2 Comments

Andreas it the ajax call that was causing the problem.
@SotirisZegiannis Yes. Hence the suggestion with iframe. Most (if not all of them) ajax downloader components you will find online work with iframes too :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.