2010-02-16 39 views
14

Estoy trabajando en algún código que genere una hoja de cálculo de Excel en el servidor y luego lo descargue al usuario. Estoy usando ExcelPackage para generar el archivo.Descargue el archivo .xlsx usando Response.TransmitFile()

La generación está funcionando bien. Puedo abrir los archivos generados usando Excel 2007 sin problemas. Pero tengo problemas para descargar el archivo con Response.TransmitFile().

En este momento, tengo el siguiente código:

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

Cuando Excel 2007 abre el archivo descargado que el anterior, se da el aviso "formato de archivo no coincide con la extensión". Después de hacer clic para pasar la advertencia, Excel muestra el contenido xml sin procesar del archivo.

Si cambio la extensión de archivo, al igual que

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

Excel 2007 da una "Excel encontró contenido no legible en el archivo" error, seguido de un diálogo que ofrece para localizar un convertidor en la web. Si hago clic en "no" en este cuadro de diálogo, Excel es capaz de cargar los datos.

También he experimentado con diferentes tipos de MIME, como application/vnd.ms-excel y application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, combinados con las extensiones de archivo .xls y .xlsx. Todas las combinaciones dan como resultado uno de los dos comportamientos mencionados anteriormente.

¿Cuál es la combinación correcta de extensión de archivo y tipo MIME para usar en este escenario? ¿Qué otra cosa podría causar esta falla, que no sea un tipo o extensión MIME incorrecta?

Para su información, esto ocurre con el servidor web de desarrollo incorporado de Visual Studio. Todavía no lo he intentado con IIS.

Respuesta

15

Definitivamente no puedo decir que su enfoque sea incorrecto, pero solo compartiré algunas observaciones para hacer algo similar.

Los encabezados son Pascal Case, a la mayoría de los navegadores no les debería importar pero cambiaría su disposición de contenido a Content-Disposition. Cambiar el Charset no debería ser necesario o relevante. Su tipo de contenido debería estar bien, solo usaría application/vnd.openxmlformats-officedocument.spreadsheetml.sheet y .xlsx si ese es realmente el contenido del archivo, de lo contrario, apéguese a application/vnd.ms-excel y .xls.

Otra cosa que debes considerar es el envío al navegador el Content-Length:

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

también han intentado esto con varios navegadores? Solo me pregunto si es un problema específico del vendedor.

Como último esfuerzo, puede configurar su tipo de contenido para la aplicación/octet-stream, y cualquier navegador debe ofrecer descargarlo, y la mayoría de los navegadores le permitirán abrirlo una vez que se haya descargado según la extensión.

+2

Ajuste de la cabecera Content-Length hizo el truco. Alternativamente, llamar a Response.End() después de TransmitFile() también funcionó. Entonces, ¿supongo que el navegador no sabía dónde estaba el final de la respuesta? – Odrade

+0

Sin configurar el encabezado Content-Length ni llamar a Response.End(), el navegador definitivamente malinterpreta el tamaño del archivo y guarda demasiados datos en el archivo. ¡Gracias por la ayuda! – Odrade

+0

Content-Length es definitivamente el camino a seguir aquí. Encontré información útil sobre Response.End() en el blog de Rick Strahl que debería compartirse con los futuros visitantes de esta página: http://west-wind.com/weblog/posts/368975.aspx – Odrade

2

uso de este

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

en su código es

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

Trate como esto

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; 
} 
Cuestiones relacionadas