【原】Asp.net產生Excel檔案並下載(更新:解決使用迅雷下載頁面而不是檔案的問題)

來源:互聯網
上載者:User

這裡採用的是在服務端先產生Excel檔案,然後利用檔案地址下載的方法。

產生Excel檔案的方法,見:【原】.Net建立Excel檔案(插入資料、修改格式、組建圖表)的方法

先試用Response.WriteFile的方法:

FileInfo fi = new FileInfo(excelFile);//excelFile為檔案在伺服器上的地址HttpResponse contextResponse = HttpContext.Current.Response;contextResponse.Clear();contextResponse.Buffer = true;contextResponse.Charset = "GB2312"; //設定了類型為中文防止亂碼的出現 contextResponse.AppendHeader("Content-Disposition", String.Format("attachment;filename={0}", excelName)); //定義輸出檔案和檔案名稱 contextResponse.AppendHeader("Content-Length", fi.Length.ToString());contextResponse.ContentEncoding = Encoding.Default;contextResponse.ContentType = "application/ms-excel";//設定輸出檔案類型為excel檔案。 contextResponse.WriteFile(fi.FullName);contextResponse.Flush();contextResponse.End();

其中第一行的excelFile為Excel檔案在伺服器上的地址,比如:“C:/Website/Excel/xx.xlsx”。

這種方法也是網上一般提供的方法,但在實際操作中,卻出現了意向不到的問題:

在Chrome下

一切正常,Excel檔案直接下載到Chrome的預設下載檔案夾中。

在Firefox下

由於安裝了FlashGot外掛程式,會先選擇應用的下載工具:

在這裡顯示是正常的,如果選擇“儲存檔案”,Excel檔案也會被儲存到預設資料夾中,但如果試用第三方下載工具,比如迅雷,會出現如下視窗:

注意到網址一欄,會在頁面實際地址後添加ViewState資訊,而另存名稱也不是Excel檔案本身的名稱,而是頁面的名稱。

點擊確定後,被下載的檔案又變成了實際檔案(有時會先變成.zip檔案,再變為實際檔案)

在IE7下

會先彈出儲存對話方塊,檔案正常,同樣因為裝了迅雷的緣故,點儲存時,彈出迅雷的下載對話方塊,和Firefox下不同,網址後面沒有ViewState資訊。

點確定,下載的則是分頁檔:

如果在迅雷的下載對話方塊中點取消,則會使用IE的下載,這裡的檔案又是正確的了:

懷疑迅雷是根據下載對話方塊中的網址重新請求下載,與發起請求的頁面已經無關,而IE又不會把ViewState資訊傳到迅雷中,導致下載的檔案不是想要的Excel頁面。

之後又嘗試了分段下載的方式,其實也是無效的,因為迅雷根本不理會你提供給它的下載機制,而且這樣在Firefox下調用迅雷時,由於分段下載的Viewstate並不包含Excel檔案的完整資訊,迅雷下載下的也是殘缺的檔案。

最後只能採用最老土的解決方案:Response.Redirect(),轉向實際檔案地址。

FileInfo fi = new FileInfo(excelFile);HttpResponse contextResponse = HttpContext.Current.Response;contextResponse.Redirect(string.Format("~/Template/{0}", excelName), false);

這樣在三個瀏覽器下測試都正常了,因為請求的是實際檔案的地址,在迅雷中顯示的也是實際檔案的地址。下載就不會出現問題。但這樣相當於告知用戶端使用者檔案的實際地址,隱私性不佳。但好在這裡並不需要太好的隱私性,而且檔案會在一定時間之後刪除,所以倒並不是太大的問題了。

上面是第一次考慮的結果,似乎還是有些懶了……

事後考慮,既然每次迅雷實際都是重新請求URL,那麼我們就應該給迅雷傳入一個能產生Excel檔案的URL。

即,在點擊“產生Excel”按鈕的時候,轉向另一個Export頁面,在這個頁面的Page_Load方法中完成組建Excel檔案、下載Excel檔案的步驟。

String fileName = Request.QueryString["FileName"];String exportName = Request.QueryString["Export"];if(fileName != null){    ExportManger.CreateExcel(fileName);//先在伺服器端建立Excel檔案。    Response.Redirect(String.Format("{0}?Export={1}",Request.Path.ToString(),fileName));//重新導向到本頁面,但Query參數變為Export。}else if(exportName != null){    ExportManger.ExportExcel(exportName);//下載Excel檔案。}

這裡頁面跳轉了兩次,第一次是產生Excel,第二次是下載Excel。

之所以跳轉兩次,是因為迅雷會捕獲最後的URL,如果產生和下載放在一起進行,那麼迅雷下載時會重複再產生一遍Excel檔案。下載Excel檔案的代碼ExportManger.ExportExcel(exportName)就使用了本文開頭介紹的Response.Write方法,也可以用分段下載的方法:

if(fi.Length > 0){    FileStream sr = new FileStream(fi.FullName,System.IO.FileMode.Open,System.IO.FileAccess.Read, System.IO.FileShare.Read);    int size = 1024;//設定每次讀取長度。    for (int i = 0; i < fi.Length / size + 1; i++)    {        byte[] buffer = new byte[size];        int length = sr.Read(buffer, 0, size);        contextResponse.OutputStream.Write(buffer, 0, length);    }    sr.Close();}else{    contextResponse.WriteFile(fi.FullName);}

這裡的結果是只產生了一次Excel並在伺服器保留,以後每次下載的時候都使用帶"Export"的參數下載相同的檔案。那麼如果需要檔案只是一次性的,每次下載都需要重建,則只需要把Export頁面的下載和產生放到一起。然後把開頭的Response.Write方法最後變成:

contextResponse.Flush();fi.Delete();contextResponse.End();
即每次響應清空後把檔案先刪除,再結束響應。

這樣就解決了利用下載工具出現的下載不能的問題,同時保護了伺服器檔案地址的隱私,並可以採用分段寫入的方法寫入大檔案,而且可以按需要即時刪除產生的檔案而不佔用伺服器空間。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.