Reputation: 602
On my page I currently have the following: a webgrid with some invoices, for every invoice I have a checkbox, for every invoice I have a pdf-Icon to view the pdf in the browser or to download the pdf.
What I'm trying to accomplish is that the user has the possibility to check some invoices and hit the button below to download these invoices as a ZIP file.
When the button is clicked an jquery function is called, this function makes an AJAX-call to my ASP.net. I pass an arrayparameter of the corresponding ID's of the invoice.
$("#download").click(function () {
var idArray = [];
$("input[type=checkbox]").each(function () {
if (this.checked)
{
idArray.push($(this).val());
}
});
$.ajax({
traditional: true,
type: "GET",
url: "/Invoices/downloadInvoices",
data: { idArray: idArray },
error: function () {
alert("error");
}
}).done(function (data) {
console.log("succes download function");
});
});
This function works as expected, in my controller I receive the array. The next step is to get the corresponding files (base64 from database) convert these files and put these file into the ZIP. This works aswell, when i check the entries of the ZIP it has the right content.
public ActionResult downloadInvoices(string[] idArray)
{
MemoryStream outputStream = new MemoryStream();
outputStream.Seek(0, SeekOrigin.Begin);
using (ZipFile zip = new ZipFile())
{
foreach (string id in idArray)
{
string json = rest.getDocumentInvoice(Convert.ToInt32(id));
byte[] file = json.convertJsonToFile();
zip.AddEntry("invoice" + id + ".pdf", file);
}
zip.Save(outputStream);
}
outputStream.WriteTo(Response.OutputStream);
Response.AppendHeader("content-disposition", "attachment; filename=invoices.zip");
Response.ContentType = "application/zip";
//return File(outputStream, "application/zip", fileDownloadName:"invoices.zip"); -- DIDN'T WORK
return new FileStreamResult(outputStream, "application/zip") { FileDownloadName = "invoices" };
}
The last step I need is that the user sees the popup to save the zip-file but this doesn't happen. When I check my debugger the ajaxcall is completed succesfully. When I check the debugger (headers) I see the request but the response headers shows contentlength : 0.
What am I missing, couldn't find any solution on the net. Hope u can help me.
Thanks in advance
{ FileDownloadName = "invoices" }
When this piece of code is deleted my contentlength isn't 0 anymore. But how can this file now be downloaded? The content the request is sending looks like the file but the popup to download the file isn't showing.
Upvotes: 1
Views: 1672
Reputation: 128
Maybe I am wrong, but to me it looks like you need to rewind memory stream to beginning before you can sent its content, add one
outputStream.Seek(0, SeekOrigin.Begin);
before
outputStream.WriteTo(Response.OutputStream);
and try again :)
Upvotes: 0
Reputation: 14967
the zip
file should be in data
, the parameter of the event done
, but as you're making an ajax query you will not see the popup for the user to download the file.
you can do two option in my expediency, the first is to send data with a form and in the attribute target
put the value _blank
to go to a new window or put for example mywindow
and do this with window.open
:
window.open('about:blank', 'mywindow');
the second option is to send data by ajax and receive a json object with ok or failure, if the action is ok save the file somewhere and on ok response you can send an id
and then do something similar to the first option but making sure that file was generated fine, and in other action in your controller recibe the id
and send the zip
file.
Upvotes: 1
Reputation: 602
Ajax doesn't allow to download files. This is for security reasons.
So to download files, don't use AJAX. Create an anchor pointing to your server side script that serves the file to be downloaded.
Upvotes: 0