4

I have something like this in my View:

        var url = '@Url.Action("DownloadZip", "Program")' + '?programNums=' + selectedRow;

        $.ajax({
            url: url,
            dataType: 'json',
            async: false,
            success: function (data) {
                if (data != "Successful") {
                    alert(data);
                }
            }
        });

The controller can return a File or can return a JSON result if there was an error. Haven't been able to get them both work together.

Here is what it looks like:

    public ActionResult DownloadZip(string programNums)
    {

        if(string.IsNullOrEmpty(programNums))
        {
          return Json("Error, blank info sent.", JsonRequestBehavior.AllowGet);
        }            

        var memoryStream = new MemoryStream();

        using (var zip = new ZipFile())
        {
            zip.AddFile("C:\\sitemap.txt");
            zip.Save(memoryStream);
        }

        memoryStream.Seek(0, 0);
        return File(memoryStream, "application/octet-stream", "archive.zip");

    }

What I am seeing is that the ajax call needs a JSON value back. Since in my case, it returns a File, it cannot work. Anyway to handle what I am doing to where it can give back a JSON or a File from the ajax call.

Nate Pet
  • 44,246
  • 124
  • 269
  • 414
  • In the ajax call it is specifying that it requires `json` as the returned type. This is different from the "application/octet-stream" being returned when you are sending the file. Try removing the line `dataType: 'json'` from the ajax call? – Shane Charles Dec 18 '12 at 21:02
  • Thanks Shane - Did removed dataType: json but that didn't work. It returned the file but was not in a readable format. Close though. – Nate Pet Dec 18 '12 at 21:06
  • I've read that AJAX is not a good method for downloading files. Here is a similar question [link](http://stackoverflow.com/questions/7578124/jquery-ajax-call-for-pdf-file-download) – Shane Charles Dec 18 '12 at 21:12

4 Answers4

3

I think you are going to run into a lot of problems with this implementation. You actually cannot upload or download files via AJAX. See the link below.

How to download file from server using jQuery AJAX and Spring MVC 3

You should use one of the two implementations shared in the question pasted above. If you use the IFRAME method, you may be able to use jQuery to check when the document is done and whether or not it succeeded.

EDIT: You can just throw a server exception (500). How you handle the 500 from the IFRAME is up to you.

Community
  • 1
  • 1
Dan Natic
  • 79
  • 2
2

Have you considered passing back JSON with a file Url?

If the file is successfully found/created. Send back a JSON result with the link to the file. Then in javascript use windows.location to retrieve the file. When there is an error, the JSON result will contain the error information and this info can be displayed to the user. For this to work, you'll need to create another endpoint (action) that can stream the file.

Chuck Conway
  • 16,287
  • 11
  • 58
  • 101
2

Your code will never work because you can't stream binary data to an Ajax request - you don't have a normal response context to write to.

You can take several approaches:

  1. If the validation passes, simply return a new link to another handler that will stream the data to the user. You would then read this link on your Javascript callback function and open it in a new window.
  2. Use an IFRAME, as DAN Natic suggested above.
  3. More complicated: Base64-encode the binary data and return it as part of the Json result. Read the base64-encoded file, decode it using Javascript (plenty of libraries to do this are found online) and do something* with the result.

* I am not sure it's possible to do anything in the case of ZIP files. You may be able to display PDF files inline inside the browser using this technique but highly doubt that it will work on all browsers. My advise is to go with option 1.

Icarus
  • 63,293
  • 14
  • 100
  • 115
1

Ajax: window.location = '/Home/download';

c#:

        public FileResult download()
        {
           return File("~/" + path, "application/pdf", string.Format(fileName));
        }
Hardik Mandankaa
  • 3,129
  • 4
  • 23
  • 32