1

I have a web api that converts datatable to excel bytes and sends it as a File. When I try to open the excel file, I get "We found a problem with some content in 'Test.xlsx'. Do you want us to try to recover as mush as we can? If you trust the source of this workbook, click yes.". When I click yes, I get "The file is corrupt and cannot be opened".

I have tried solutions mentioned in the following stack overflow questions:

ASP.NET MVC FileResult is corrupting files

Excel file (.xlsx) created by saving byte stream in C# cannot be opened

issue with returning HttpResponseMessage as excel file in WebAPI

'The file is corrupt and cannot be opened' OpenXML

[HttpPost]
public FileResult GetExcelFile(string parameters)
{
      byte[] contents = generateContents(parameters);

      // Method 1:
      //Response.Clear();
//      Response.ContentType = "application/octet-stream";
  //    Response.AddHeader("Content-Disposition", "attachment; filename=" + "Test.xlsx");
    //  Response.AddHeader("Content-Length", contents.Length.ToString());
     // Response.BinaryWrite(contents);
//      Response.Flush();
  //    Response.Close();
    //  Response.End();


     return File(contents, "application/octet-stream", "Test.xlsx");
}

$.ajax({
            url: webMethod,
            type: "POST",
            data: jQuery.param(parameters),
            success: function (result, status, xhr) {
                var filename = "";
                var disposition = xhr.getResponseHeader('Content-Disposition');
                if (disposition && disposition.indexOf('attachment') !== -1) {
                    var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                    var matches = filenameRegex.exec(disposition);
                    if (matches != null && matches[1]) {
                        filename = matches[1].replace(/['"]/g, '');
                    }
                }

                var blob = new Blob([result]);
                var link = document.createElement('a');
                link.href = window.URL.createObjectURL(blob);
                link.download = filename;
                link.click();
            }
        });

Thanks in advance for your help!

UPDATE:

The file returned from controller is 4 KB size and on the ajax side, the received blob size is 7 KB.

user2782405
  • 393
  • 1
  • 6
  • 20
  • It may not be a problem from client side, it could be in the way you are generating document. Can you verify that first? Maybe instead of calling generateContents call, you can read any valid excel file and see. – Krishna Chaithanya Muthyala Jul 25 '19 at 14:18
  • @KrishnaChaithanyaMuthyala: Same error with a valid excel file. Any suggestions? – user2782405 Jul 26 '19 at 00:27
  • ok...so the problem seems to be with client side then...first of all, why is this a POST, if it is just getting data? Then why are you not using correct mime-type while returning, as mentioned in the first link you gave? – Krishna Chaithanya Muthyala Jul 26 '19 at 10:16
  • And what is your platform? ASP.NET MVC with razor view along with webAPI? Do you want this file to be downloaded on clicking a button or something? – Krishna Chaithanya Muthyala Jul 26 '19 at 10:18
  • I changed it to HttpGet and also tried with `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` and `application/vnd.ms-excel`. https://stackoverflow.com/questions/44559457/download-xlsx-getting-corrupted https://stackoverflow.com/questions/51150454/downloading-xlsx-file-returning-corrupt-file Same response – user2782405 Jul 26 '19 at 19:11
  • Can you show the code for the `generateContents` method? – Brian Rogers Jul 30 '19 at 22:33
  • I have created a sample excel file and reading bytes of that file for testing. `byte[] contents = System.IO.File.ReadAllBytes("C:\\Test\\TestingFile.xlsx");` – user2782405 Jul 30 '19 at 23:55
  • I have found one more thing. The file returned from controller is of size 4 KB and on the ajax side, the received blob size is 7 KB. Any ideas? – user2782405 Jul 31 '19 at 00:33

2 Answers2

0

I'm not sure if this could help. At the moment I'm going through a similar task with other kind of problems intercepting when my file is downloaded in the javascript side. But the part of create and download is working like a charm. I'm not using ajax but here is my code:

In the javascript I'm just calling the Controller and the HttpResponseMessage:

    XlsGlarm: function () {
        $('#mdlWait').modal('show');
        committente = globalCommittente;
        periodo = globalPeriodo;
        location.href = "Exports/XlsGLARM?CfCommit=" + committente + "&Periodo=" + periodo;
        $('#mdlWait').modal('hide');
    }

and in the MVC controller:

        public HttpResponseMessage XlsGLARM(string CfCommit, string Periodo)
    {
        // here I load an Excel Template and build the workbook
        // and fill it. But iit's not realted to your question.

            using (MemoryStream tmpStream = new MemoryStream())
            {
                Response.Clear();
                Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
                workbook.Write(tmpStream);
                Response.BinaryWrite(tmpStream.ToArray());
                Response.End();
                return null;
            }

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

At the end I get my file to download from the browser, I've tested it with Chorme, IE and Modzilla.

René R
  • 116
  • 2
  • R: I was able to download the excel file with no issues. But only one row is written to the file and rest of the rows are missing. Did you run into this issue? – user2782405 Aug 14 '19 at 06:45
0

For me it's working fine with as many lines I get from the source db. I have also solved the waiting process that intercepts the download.

 EsportaListaExcell: function (AnnoImposta) {
        Metronic.blockUI({ target: "#gestione", animate: true });

        var url = "Controllers/ExportController.aspx?Anno=" + AnnoImposta + "&Procedura=Flussi&Filtro=" + jQuery('#gwFlusso_filter input').val() +
                                                    "&CodiceEsito=" + jQuery('#gwFlusso_filter_stato select').val();
        window.location.href = url;

        $.ajax({
            url: url,
            //...                
            error: function () {
                Metronic.unblockUI('#gestione');
            },
            complete: function () {
                Metronic.unblockUI('#gestione');
                //hide loading?
            }
        });

    },
René R
  • 116
  • 2