2010-02-16 44 views
14

Tôi đang làm việc trên một số mã tạo ra một máy chủ bảng tính Excel và sau đó tải xuống nó cho người dùng. Tôi đang sử dụng ExcelPackage để tạo tệp.Tải xuống tệp .xlsx bằng Response.TransmitFile()

Thế hệ đang hoạt động tốt. Tôi có thể mở các tập tin được tạo ra bằng cách sử dụng Excel 2007 mà không có vấn đề gì. Tuy nhiên, tôi đang gặp sự cố khi tải xuống tệp với Response.TransmitFile().

Ngay bây giờ, tôi có đoạn mã sau:

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

Khi Excel 2007 mở tập tin tải về như trên, nó mang lại cho các "định dạng file không phù hợp với phần mở rộng" cảnh báo. Sau khi nhấp vào cảnh báo, Excel sẽ hiển thị nội dung xml thô của tệp.

Nếu tôi thay đổi phần mở rộng tập tin, như vậy

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

Excel 2007 đưa ra một "Excel tìm thấy nội dung không thể đọc được trong tập tin" lỗi, tiếp theo là một hộp thoại cung cấp để xác định vị trí một bộ chuyển đổi trên web. Nếu tôi nhấp vào "không" trên hộp thoại này, Excel có thể tải dữ liệu.

Tôi cũng đã thử nghiệm với các loại MIME khác nhau, như application/vnd.ms-excelapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet, được kết hợp với các đuôi tệp .xls và .xlsx. Tất cả các kết hợp đều dẫn đến một trong hai hành vi nêu trên.

Kết hợp chính xác của phần mở rộng tệp và loại MIME để sử dụng trong trường hợp này là gì? Điều gì khác có thể gây ra lỗi này, ngoại trừ loại MIME hoặc phần mở rộng không đúng?

FYI, điều này xảy ra với máy chủ web phát triển tích hợp của Visual Studio. Tôi chưa thử với IIS.

Trả lời

15

Tôi chắc chắn không thể nói rằng có gì sai với cách tiếp cận của bạn, nhưng tôi sẽ chỉ chia sẻ một số quan sát từ làm một cái gì đó tương tự.

Tiêu đề là Pascal Case, hầu hết các trình duyệt không nên quan tâm nhưng tôi sẽ thay đổi bố cục nội dung của bạn thành Nội dung. Thay đổi Bộ ký tự không cần thiết hoặc có liên quan. Loại nội dung của bạn sẽ ổn, tôi sẽ chỉ sử dụng application/vnd.openxmlformats-officedocument.spreadsheetml.sheet và .xlsx nếu đó thực sự là nội dung của tệp, nếu không thì gắn với application/vnd.ms-excel và .xls.

Một điều bạn nên cân nhắc được gửi trình duyệt Content-Length:

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

Cũng có bạn đã thử điều này với nhiều trình duyệt? Chỉ cần tự hỏi nếu đó là một vấn đề của nhà cung cấp cụ thể.

Là nỗ lực cuối cùng, bạn có thể đặt Content-Type thành ứng dụng/octet-stream và bất kỳ trình duyệt nào nên cung cấp để tải xuống và sau đó hầu hết các trình duyệt sẽ cho phép bạn mở nó sau khi được tải xuống dựa trên tiện ích.

+2

Thiết header Content-Length đã làm các trick. Cách khác, gọi Response.End() sau khi TransmitFile() cũng làm việc. Vì vậy, tôi đoán trình duyệt không biết kết thúc của phản hồi là ở đâu? – Odrade

+0

Nếu không đặt tiêu đề Content-Length hoặc gọi Response.End(), trình duyệt chắc chắn hiểu sai kích thước tệp và lưu quá nhiều dữ liệu vào tệp. Cảm ơn đã giúp đỡ! – Odrade

+0

Độ dài nội dung chắc chắn là cách để đến đây. Tôi đã tìm thấy một số thông tin hữu ích về Response.End() trên blog của Rick Strahl nên được chia sẻ với khách truy cập trong tương lai của trang này: http://west-wind.com/weblog/posts/368975.aspx – Odrade

2

sử dụng này

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

trong mã của bạn là

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

Hãy thử như thế này

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; 
} 
Các vấn đề liên quan