I am trying to download a file from a url with ajax and asp.net mvc 5 this is my controller:
[HttpPost]
public ActionResult DownloadDocument(DownloadModel model){
urlFile = "http://www.storage.net/data/pdf-xml/" + model.nombre.ToLower() + model.Extencion;
//Create a stream for the file
Stream stream = null;
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffers = new Byte[bytesToRead];
// The number of bytes read
try{
//Create a WebRequest to get the file
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(urlFile);
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileResp.ContentLength > 0)//aquí reviso si el archivo contiene datos (existe o no)
{
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
//var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
Response.ContentType = "application/octet-stream";
//Name the file
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + model.nombre + model.Extencion + "\"");
Response.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do{
// Verify that the client is connected.
if (Response.IsClientConnected){
// Read data into the buffer.
length = stream.Read(buffers, 0, bytesToRead);
// and write it out to the response's output stream
Response.OutputStream.Write(buffers, 0, length);
// Flush the data
Response.Flush();
//Clear the buffer
buffers = new Byte[bytesToRead];
}else{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
}catch (Exception e){
d2.Add("Error", e.Message);
}finally{
if (stream != null){
//Close the input stream
stream.Close();
}else if (d2.Count < 1){
d2.Add("Error", "El Archivo no existe");
}
}
//mostramso el mensaje de que no existe el archivo
return Json(serializer.Serialize(d2));
}
If the form is directed to the controller, it performs the download, but if a file did not exist, it would send me a message which I show in my view but it is shown in a separate view.
And I want the download to be done through jquery ajax since this is the way I can show the message, but the download does not appear in the browser
This is my form:
<form method="post" class="form-horizontal" role="form" name="formDownload" id="formDownload140464">
<input type="hidden" value="AAA010101AAA" id="rfcCompany" name="rfcCompany">
<input type="hidden" value="40464" id="id" name="id">
<input type="hidden" value=".pdf" id="Extencion" name="Extencion">
<input id="Nombre" name="Nombre">
<button type="button" class="btn btn-primary btn-sm previewPopover" title="Descargar" onclick="MostrarMensaje(40464)">
<span class="elusive icon-download-alt"></span>
</button>
</form>
My ajax function is this, I use it to display the message.
function MostrarMensaje(id) {
$('#formDownload1' + id).on("submit", function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '/Portal/DownloadDocument',
data: $('#formDownload1' + id).serialize(),
success: function (data) {
var d = JSON.parse(data);
$.jGrowl("" + d["Error"], {
header: "Error",
//sticky: true,
theme: "red"
});
}
});
});
}
With this the message is displayed but the download does not perform.
I have seen that many pass the url in the data and download with window.location.href = d["Url"];
, but my problem here with this code is that I will not know if the file exists or not and it will download an empty file.
You cannot open the browser download dialog from JavaScript. You have to perform a navigation to the document for the browser to open the download dialog.
If you want to previously check if the file exists, what you can do is an action that checks the existence of the file. In this way you call the action through ajax to verify that the file exists and, if so, you navigate to the download url with document.location.
Another alternative to open the download dialog is the HTML5 download attribute that allows you to create a link that downloads a file but it would not fit your case and is not yet supported by all browsers. Yes, Chrome, Firefox, Edge and Opera support it, but not Internet Explorer in any of its versions and if I remember correctly neither Safari.
It is not valid to send a byte array as json to perform the download, but you send it as a file
ASP.NET MVC Uploading and Downloading Files
and you use a library as being
jquery.fileDownload
to perform the download using javascript