download file from url with ajax and asp.net mvc 5

3

I'm 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 does the download, but if a file did not exist it would send me a message which I show it in my view but it is shown in a separate view.
And I want the download to be made through jquery ajax since that is the way I can show the message, but I do not see the download 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"
                });
            }
        });
    });
} 

This shows the message but does not download it.
I have seen that many pass the url in the data and do the 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 I downloaded an empty file.

    
asked by JuankGlezz 06.06.2016 в 19:47
source

2 answers

2

You can not open the browser download dialog from JavaScript. You have to make a navigation to the document so that the browser opens the download dialog.

If you want to check beforehand if the file exists, what you can do is an action that verifies the existence of the file. In this way you call to action through ajax to verify that the file exists and, if so, you make the navigation to the download url with document.location.

Another alternative to open the download dialog is the download attribute of HTML5 that allows you to create a link that performs the download of a file but it would not fit your case and also is not yet supported by all browsers. Yes it is supported by Chrome, Firefox, Edge and Opera, but not Internet Explorer in any of its versions and if I remember neither Safari badly.

    
answered by 06.06.2016 / 20:31
source
0

It is not valid to send a byte array as json to perform the download, but send it as a file

[HttpPost]
public FileResult DownloadDocument(DownloadModel model){
  //resto codigo
  return File(...)
}

ASP.NET MVC Uploading and Downloading Files

and you use a library like being

jquery.fileDownload

to download using javascript

    
answered by 06.06.2016 в 20:38