2010-02-16 16 views
14

Sto lavorando su un codice che genera un foglio di calcolo di Excel lato server e poi lo scarica per l'utente. Sto usando ExcelPackage per generare il file.file Download .xlsx utilizzando Response.TransmitFile()

La generazione sta lavorando bene. Posso aprire i file generati utilizzando Excel 2007 senza problemi. Ma, ho problemi a scaricare il file con Response.TransmitFile().

In questo momento, ho il seguente codice:

//Generate the file using ExcelPackage 
string fileName = generateExcelFile(dataList, "MyReportData"); 

Response.AddHeader("content-disposition", "attachment;filename=FileName.xls"); 
Response.ContentType = "application/vnd.xls" 
Response.Charset = ""; 
Response.TransmitFile(fileName); 

Quando Excel 2007 apre il file scaricato come sopra, dà l'avvertimento "formato di file non corrisponde estensione". Dopo aver fatto clic sull'avviso, Excel visualizza i contenuti xml originali del file.

Se cambio l'estensione del file, in questo modo

Response.AddHeader("content-disposition", "attachment;filename=FileName.xlsx"); 

Excel 2007 fornisce un "Excel trovato contenuto illeggibile nel file" errore, seguito da una finestra di dialogo che offre per individuare un convertitore sul web. Se faccio clic su "no" in questa finestra di dialogo, Excel è in grado di caricare i dati.

Ho anche sperimentato diversi tipi MIME, come application/vnd.ms-excel e application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, combinato con estensioni di file .xls e .xlsx. Tutte le combinazioni risultano in uno dei due comportamenti sopra menzionati.

Qual è la corretta combinazione di estensione del file e il tipo MIME da utilizzare in questo scenario? Cos'altro potrebbe causare questo errore, a parte un tipo o un'estensione MIME impropria?

FYI, questo sta accadendo con il server web integrato di sviluppo di Visual Studio. Non ho ancora provato con IIS.

risposta

15

Non posso sicuramente dire che ci sia qualcosa di sbagliato con il vostro approccio, ma mi limiterò a condividere alcune osservazioni da fare qualcosa di simile.

intestazioni sono Pascal caso, la maggior parte dei browser non dovrebbero preoccuparsi, ma vorrei cambiare il Content-Disposition per Content-Disposition. Cambiare il Charset non dovrebbe essere necessario o rilevante. Il tuo tipo di contenuto dovrebbe andare bene, userei solo application/vnd.openxmlformats-officedocument.spreadsheetml.sheet e .xlsx se questo è effettivamente il contenuto del file, altrimenti rimani con application/vnd.ms-excel e .xls.

Un'altra cosa che dovrebbe prendere in considerazione è l'invio al browser il Content-Length:

Response.AddHeader("Content-Length", new System.IO.FileInfo("FileName.xlsx").Length); 

Inoltre avete provato questo con più browser? Mi chiedo solo se si tratta di un problema specifico del fornitore.

Come ultimo tentativo, puoi impostare il tuo Content-Type su application/octet-stream, e qualsiasi browser dovrebbe offrire di scaricarlo, e quindi la maggior parte dei browser ti permetterà di aprirlo dopo che è stato scaricato in base all'estensione.

+2

Impostazione dell'intestazione Content-Length ha fatto il trucco. In alternativa, anche chiamata Response.End() dopo TransmitFile() ha funzionato. Quindi, immagino che il browser non sapesse dove si trovava la fine della risposta? – Odrade

+0

Senza impostare l'intestazione Content-Length o chiamando Response.End(), il browser interpreta in modo errato le dimensioni del file e salva troppi dati nel file. Grazie per l'aiuto! – Odrade

+0

Content-Length è sicuramente il modo per andare qui. Ho trovato alcune informazioni utili su Response.End() sul blog di Rick Strahl che dovrebbero essere condivise con i futuri visitatori di questa pagina: http://west-wind.com/weblog/posts/368975.aspx – Odrade

2

uso questo

HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=\"filename + ".zip" + "\""); 
       Response.TransmitFile(zipPath); 
       Response.Flush(); 
       Response.Close(); 
       Response.End(); 

nel codice è

Response.AddHeader("content-disposition", "attachment;filename=\FileName.xlsx\"); 
0

Prova come questo

public void DataTableToExcel(DataTable dt, string Filename) 
{ 
    MemoryStream ms = DataTableToExcelXlsx(dt, "Sheet1"); 
    ms.WriteTo(HttpContext.Current.Response.OutputStream); 
    HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + Filename); 
    HttpContext.Current.Response.StatusCode = 200; 
    HttpContext.Current.Response.End(); 
} 

public static MemoryStream DataTableToExcelXlsx(DataTable table, string sheetName) 
{ 
    MemoryStream result = new MemoryStream(); 
    ExcelPackage excelpack = new ExcelPackage(); 
    ExcelWorksheet worksheet = excelpack.Workbook.Worksheets.Add(sheetName); 
    int col = 1; 
    int row = 1; 
    foreach (DataColumn column in table.Columns) 
    { 
     worksheet.Cells[row, col].Value = column.ColumnName.ToString(); 
     col++; 
    } 
    col = 1; 
    row = 2; 
    foreach (DataRow rw in table.Rows) 
    { 
     foreach (DataColumn cl in table.Columns) 
     { 
      if (rw[cl.ColumnName] != DBNull.Value) 
       worksheet.Cells[row, col].Value = rw[cl.ColumnName].ToString(); 
      col++; 
     } 
     row++; 
     col = 1; 
    } 
    excelpack.SaveAs(result); 
    return result; 
} 
Problemi correlati