2012-03-07 14 views
13

Quando provo a generare un file Excel utilizzando EPPlus, Excel mi danno il seguente messaggio di errore:Generazione di un file Excel con EPPlus sta fallendo

Excel non può aprire il file 'myfilename.xlsx' perché il formato di file o l'estensione del file non è valida. Verificare che il file non sia stato danneggiato e che l'estensione del file corrisponda al formato del file.

Ecco il mio codice:

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); 
    } 
} 

Qualsiasi idea di cosa sto facendo male?

+0

L'errore dice 'myfilename.xslx' mentre il tuo codice mostra 'myfilename.xlsx'. Quale stai usando veramente? –

+0

Risposta [ieri] (http://stackoverflow.com/a/9574414/284240). Presumo che questo sia lo stesso problema. –

+0

@ M.Babcock - xlsx, era un errore di battitura. Modificherò la domanda. –

risposta

27

Tutto quello che dovete fare è ripristinare la posizione di flusso. stream.Position = 0;

Il non deve scrivere direttamente sulla risposta, non è il modo MVC. Non segue la pipeline MVC corretta e accoppia strettamente il codice di azione del controller all'oggetto Response.

Quando si aggiunge un nome file come terzo parametro in File(), MVC aggiunge automaticamente l'intestazione Content-Disposition corretta ... quindi non è necessario aggiungerlo manualmente.

Il corto di esso è, questo è ciò che si vuole:

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

Quindi, domanda su questo, sto usando un metodo simile anche se attualmente sto restituendo un FileStreamResponse invece di un oggetto file.Il problema che sto incontrando è che se l'utente fa più di una richiesta mentre viene creato il primo file, sembra che tutti vengano bloccati e il metodo saveas non viene mai completato. Ti sei imbattuto in questo con EPPlus? – Shawn

10

Il codice non mostra stream in fase di scrittura su HttpResponse - presumibilmente eseguito nel metodo File che non è stato pubblicato.

Un modo che funziona è la seguente:

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

Il metodo 'File' fa parte di' ASP.Net MVC'. Proverò in questo modo! –

+0

Strano, ora dice "Excel ha trovato contenuti illeggibili in 'myfilename.xlsx'. Vuoi recuperare il contenuto di questa cartella di lavoro? Se ti fidi dell'origine di questa cartella di lavoro, fai clic su Sì." Se faccio clic su Sì, sembra funzionare, ma non ho idea di cosa stia dando quell'errore. –

+0

Ho visto quel messaggio di errore prima, IIRC è successo quando è stato omesso Response.Clear(). Un'altra possibilità è che un bug di EPPlus produca dati non validi nel file. Puoi verificare quale è salvando il file sul server e vedendo se ottieni lo stesso errore quando lo apri sul server. – Joe

2

Simile alla risposta di Joe, avevo ancora chiamare 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(); 
    } 
Problemi correlati