jruiz
jruiz

Reputation: 95

Safari adding .html to download xlsx using epplus jquery.fileDownload.js

I am using MVC c# code to generate a excel file and then download, i am using EPPLUS, everything works fine except on Safari on Mac, when I try to create the file when it is download that added .html at the end, for example, file.xlsx.html I don't have idea how i can solve that.

    $.fileDownload(url, {
        httpMethod: 'POST',
        data: dtColumns,
        successCallback: function() {
            //code
        },
        failCallback: function() {
            //code

        }
    });

public Stream ExportDataset(IEnumerable dataset, IList columnsToExport,string template) { // Grouping works on anon types so we can group the export into their own tables var groupings = dataset.GroupBy(i => i.GetType());

        using (var package = new ExcelPackage(new FileInfo(GetTemplateFilePath(template)), true))
        {
            var ws = package.Workbook.Worksheets[1];

            if (groupings.Any())
            {
                // add each "anon type matched grouping"
                foreach (var grouping in groupings)
                {
                    // because of EPP inheritance bug of T, we can just use dataTable
                    var dataTable = new DataTable(grouping.Key.Name);
                    var properties = grouping.Key.GetProperties(); // Get anon type Properties
                    var columns = columnsToExport.OrderBy(x => x.Position);

                    foreach (var property in columns.Where(column => column.IsVisible).SelectMany(column => properties.Where(property => property.Name.Equals(column.Name))))
                    {
                        dataTable.Columns.Add(property.Name);
                    }

                    foreach (var item in grouping.ToList())
                    {
                        var dataRow = dataTable.NewRow();

                        foreach (var p in columns.Where(column => column.IsVisible).SelectMany(column => properties.Where(property => property.Name.Equals(column.Name))))
                        {
                            dataRow[p.Name] = p.GetValue(item);
                        }

                        dataTable.Rows.Add(dataRow);
                    }

                    ws.Cells[1, 1].LoadFromDataTable(dataTable, PrintHeaders: true);
                    ws.Cells.AutoFitColumns();
                }
            }
            else
            {
                // This case is when there is no data on the table to load the Excel so we create an empty sheet but we add the headers
                var datasetStructure = dataset.GetType().GetGenericArguments()[0];

                // because of EPP inheritance bug of T, we can just use dataTable
                var dataTable = new DataTable(datasetStructure.Name);
                var properties = datasetStructure.GetProperties(); // Get anon type Properties

                foreach (var property in properties)
                {
                    dataTable.Columns.Add(property.Name);
                }

                ws.Cells[1, 1].LoadFromDataTable(dataTable, PrintHeaders: true);
                ws.Cells.AutoFitColumns();
            }

            var fileStream = new MemoryStream();
            package.SaveAs(fileStream);

            return fileStream;
        }
    }

on controller:

return new CustomFileResult(fileStream, fileName);

public class CustomFileResult : IHttpActionResult { private readonly Stream _fileContent; private readonly string _fileName;

    public CustomFileResult(Stream fileContent, string fileName)
    {
       _fileContent = fileContent;
       _fileName = fileName;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            var response = new HttpResponseMessage();
            var fileDownloadFail = false;

            if (_fileContent == null || _fileContent.Length == 0)
            {
                response.StatusCode = HttpStatusCode.InternalServerError;
                fileDownloadFail = true;

            }
            else
            {
                response.StatusCode = HttpStatusCode.OK;
                _fileContent.Position = 0;
                response.Content = new StreamContent(_fileContent);

                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = _fileName,
                };
            }

            //Required for plugin jquery.fileDownload.js

            var cookie = new CookieHeaderValue("fileDownload", "true") { Path = "/" };

            response.Headers.AddCookies(new CookieHeaderValue[] { cookie }); 

            return response;

        }, cancellationToken);
    }
}

Upvotes: 0

Views: 842

Answers (1)

jruiz
jruiz

Reputation: 95

The solution for that is add the header ContentType for excel (application/vnd.ms-excel) on the response. The default is text/HTML, so Safari for this reason doesn't understand the response contains excel file, so add this line:

response.Content.Headers.ContentType  = new MediaTypeHeaderValue("application/vnd.ms-excel");

the problem was solved.

Upvotes: 3

Related Questions