Home > Back-end >  C# Return File not working to download an Excel file
C# Return File not working to download an Excel file

Time:03-30

I'm trying to download a file like this with an MVC project:

Controller:

  [HttpPost]
        [ActionName("ExportList")]
        public async Task<IActionResult> ExportList(List<object> objectList)
        {
            var fileName = "fileName" ".xlsx";
            try
            {
                var fileContent = await _serviceLayer.ExportListToExcel(objectList);
                return File(fileContent, "application/vnd.ms-excel", fileName);
                // return new JsonResult("ok");
            }
            catch(Exception ex)
            {
                return BadRequest(ex.Message);
            }
        } 

then my service layer:

public Task<byte[]> ExportListToExcel(List<object> objectList)
        {
            try
            {
               using(var workbook = new XLWorkbook())
                {
                    var worksheet = workbook.Worksheets.Add("Report");
                    var currentRow = 1;

                    #region Header
                    worksheet.Cell(currentRow, 1).Value = "val1";
                    worksheet.Cell(currentRow, 2).Value = "val2";
                    worksheet.Cell(currentRow, 3).Value = "val3";
                    #endregion

                    #region Body
                    foreach(var obj in objectList)
                    {
                        currentRow  ;
                        worksheet.Cell(currentRow, 1).Value = obj.val1;
                        worksheet.Cell(currentRow, 2).Value = obj.val2;
                        worksheet.Cell(currentRow, 3).Value = obj.val3;
                    }
                    #endregion

                    using(var stream = new MemoryStream())
                    {
                        workbook.SaveAs(stream);
                        var content = stream.ToArray();

                        return Task.FromResult(content);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error");
            }
        }

I call the controller method with ajax:

 function exportList() {
                 $.ajax({
                    type: "POST",
                    url: "@Url.Action("ExportList")",
                     data: { objectList: objectList},
                    dataType: "json",
                    success: function (data) {
                       //show success message
                    }, error: function (req, status, error) {
                       //show error message
                  }
            });
        }

I read a lot of posts and this is bassically what they suggest to download the file, but instead I'm returning to the view with the following error Message and the file is not being downloaded but the controller is not throwing any kind of exception message:

enter image description here

Any ideas to download the file?

CodePudding user response:

Try Blob responseType,

$.ajax({
   type: "POST",
   url: "@Url.Action("ExportList")",
   data: { objectList: objectList},
   xhrFields: {
      responseType: 'blob' // FileContentResult will return as blob
   },
   success: function (data) {
      const url = window.URL.createObjectURL(data); // create url from blob
      const link = document.createElement('a'); // create anchor at DOM
      link.href = url; 
      link.setAttribute('download', 'file.xlsx'); // download attribute
      document.body.appendChild(link);
      link.click(); // trigger click for download
   },
   error: function (req, status, error) {
      //show error message
   }
});

CodePudding user response:

Hi your problem is your javascript function exportList() it's better create a redirect on where the file is and then download it. In your export method

That will be part of your ExportList controller method:

// Generate a new unique identifier against which the file can be stored
                string handle = Guid.NewGuid().ToString();    
                using (MemoryStream memoryStream = new MemoryStream())
                {
                   //save your file to memory stream
                    workbook.SaveAs(memoryStream);
                    memoryStream.Position = 0;
                    TempData[handle] = memoryStream.ToArray();
                }
    
                // Note we are returning a filename as well as the handle
                return new JsonResult()
                {
                    Data = new { FileGuid = handle, FileName = "exporfile.xlsx" , FileType="xlsx"}
                };

your download file should look like this:

 public virtual ActionResult Download(string fileGuid, string fileName, string fileType)
        {
            if (TempData[fileGuid] != null)
            {
                byte[] data = TempData[fileGuid] as byte[];
                if (fileType == "xlsx" || fileType == "xls")
                {
                    return File(data, "application/vnd.ms-excel", fileName);
                }
                else if (fileType == "pdf")
                {
                    return File(data, "application/pdf", fileName);
                }
                else
                {
                    //sin especificar...
                    return File(data, "application/octet-stream", fileName);
                }
            }
            else
            {
               
                return new EmptyResult();
            }
        }

then change your exportlist method:

 function exportList() {
                 $.ajax({
                    type: "POST",
                    url: "@Url.Action("ExportList")",
                     data: { objectList: objectList},
                    dataType: "json",
                    success: function (data) {
                       var response = JSON.parse(data);
                    window.location = '/YourController/Download?fileGuid='   response.FileGuid   '&filename='   response.FileName  '&fileType='   response.FileType;
                    }, error: function (req, status, error) {
                       //show error message
                  }
        });
    }
  • Related