2012-03-07 16 views
13

Cuando intento generar un archivo de Excel usando EPPlus, Excel dame el siguiente mensaje de error:Generación de archivo de Excel con EPPlus está fallando

Excel no puede abrir el archivo 'myfilename.xlsx' debido a que el formato de archivo o la extensión de archivo no es válida. Verifique que el archivo no se haya dañado y que la extensión del archivo coincida con el formato del archivo.

Aquí está mi código:

public ActionResult Index() 
{ 
    using (ExcelPackage package = new ExcelPackage()) 
    { 
     // I populate the worksheet here. I'm 90% sure this is fine 
     // because the stream file size changes based on what I pass to it. 

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

     string fileName = "myfilename.xlsx"; 
     string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 

     var cd = new System.Net.Mime.ContentDisposition 
     { 
      Inline = false, 
      FileName = fileName 
     }; 
     Response.AppendHeader("Content-Disposition", cd.ToString()); 
     return File(stream, contentType, fileName); 
    } 
} 

Alguna idea de lo que estoy haciendo mal?

+0

dice 'El error mientras myfilename.xslx' su código muestra 'myfilename.xlsx'. ¿Cuál estás realmente usando? –

+0

Respondido [ayer] (http://stackoverflow.com/a/9574414/284240). Supongo que este es el mismo problema. –

+0

@ M.Babcock - xlsx, fue un error tipográfico. Voy a editar la pregunta. –

Respuesta

27

Todo lo que necesita hacer es restablecer la posición corriente. stream.Position = 0;

Usted no debe escribir directamente en la respuesta, no es el modo MVC. No sigue la canalización MVC correcta y acopla estrechamente el código de acción del controlador al objeto Response.

Cuando agrega un nombre de archivo como el tercer parámetro en File(), MVC agrega automáticamente el encabezado Content-Disposition correcto ... por lo que no debería necesitar agregarlo manualmente.

El corto de él es que esto es lo que quiere:

public ActionResult Index() 
{ 
    using (ExcelPackage package = new ExcelPackage()) 
    { 
     // I populate the worksheet here. I'm 90% sure this is fine 
     // because the stream file size changes based on what I pass to it. 

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

     string fileName = "myfilename.xlsx"; 
     string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 

     stream.Position = 0; 
     return File(stream, contentType, fileName); 
    } 
} 
+0

Así que, pregunta sobre esto, estoy usando un método similar aunque actualmente estoy devolviendo FileStreamResponse en lugar de un objeto de archivo.El problema al que me estoy enfrentando es que si el usuario realiza más de una solicitud mientras se está construyendo el primer archivo, parece que todos se bloquean y el método de guardar nunca se completa. ¿Te has encontrado con esto con EPPlus? – Shawn

10

Su código no muestra stream en el HttpResponse - supuestamente en el método File que no ha publicado.

Una manera en que funciona es la siguiente:

Response.Clear(); 
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
Response.AddHeader(
      "content-disposition", String.Format(CultureInfo.InvariantCulture, "attachment; filename={0}", fileName)); 
Response.BinaryWrite(package.GetAsByteArray()); 
Response.End(); 
+0

El método 'File' es parte de' ASP.Net MVC'. ¡Lo intentaré de esta manera! –

+0

Extraño, ahora dice "Excel encontró contenido ilegible en 'myfilename.xlsx'. ¿Desea recuperar el contenido de este libro? Si confía en el origen de este libro de trabajo, haga clic en Sí". Si hago clic en Sí, parece funcionar, pero no tengo idea de qué es lo que está dando ese error. –

+0

He visto ese mensaje de error antes, IIRC sucedió cuando se omitió Response.Clear(). Otra posibilidad es que un error de EPPlus genere datos no válidos en el archivo. Puede probar cuál es guardando el archivo en el servidor y viendo si obtiene el mismo error al abrirlo en el servidor. – Joe

2

Similar a la respuesta de Joe, todavía tenía que llamar Response.ClearHeaders():

protected void btnDownload_Click(object sender, EventArgs e) 
    { 

     ExcelPackage pck = new ExcelPackage(); 
     var ws = pck.Workbook.Worksheets.Add("Sample2"); 

     ws.Cells["A1"].Value = "Sample 2"; 
     ws.Cells["A1"].Style.Font.Bold = true; 
     var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect); 
     shape.SetPosition(50, 200); 
     shape.SetSize(200, 100); 
     shape.Text = "Sample 2 outputs the sheet using the Response.BinaryWrite method"; 
     Response.Clear();  
     Response.ClearHeaders(); 
     Response.BinaryWrite(pck.GetAsByteArray()); 
     Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
     Response.AddHeader("content-disposition", "attachment; filename=Sample2.xlsx"); 
     Response.End(); 
    } 
Cuestiones relacionadas