Hopes

          Start Here..

           

          Asp.net生成Excel文件并下載(更新:解決使用迅雷下載頁面而不是文件的問題)


          一)

          如果在迅雷的下載對話框中點取消,則會使用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();
          即每次響應清空后把文件先刪除,再結束響應。

          這樣就解決了利用下載工具出現的下載不能的問題,同時保護了服務器文件地址的隱私,并可以采用分段寫入的方法寫入大文件,而且可以按需要即時刪除生成的文件而不占用服務器空間。


          二)

          用超級鏈接就行. 
          <a href="這里用ASP.NET輸出數據庫中你的文件名稱(包括路徑)" title="點擊下載(這個標記是你鼠標劃過鏈接是提示的文字)" target="_blank">文件名稱</a> 
          target="_blank" 是新打開網頁,而不是在當前頁跳轉.

          新建一個download.aspx?filename='aa'頁面專門用來下載,并將要下載的文件名傳給這個頁面,然后在這個頁面寫以下代碼
          string filename=Request.QueryString(["filename"]);
          FileInfo DownloadFile = new FileInfo("../FILE/"+filename); //設置要下載的文件
          if(DownloadFile.isExists)
          {
          Response.Clear(); //清除緩沖區流中的所有內容輸出
          Response.ClearHeaders(); //清除緩沖區流中的所有頭
          Response.Buffer = false; //設置緩沖輸出為false
          Response.ContentType = "application/octet-stream";//將 HTTP 頭添加到輸出流
          Response.AppendHeader("Content-Disposition", "attachment;filename=" +HttpUtility.UrlEncode(DownloadFile.FullName, System.Text.Encoding.UTF8));
          Response.AppendHeader("Content-Length", DownloadFile.Length.ToString());
          Response.WriteFile(DownloadFile.FullName);
          Response.Flush(); //向客戶端發送當前所有緩沖的輸出
          Response.End(); //將當前所有緩沖的輸出發送到客戶端
          Response.Close();
          }



          posted on 2012-10-26 21:09 ** 閱讀(159) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          公告

          你好!

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章分類

          文章檔案

          新聞檔案

          相冊

          收藏夾

          C#學習

          友情鏈接

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 鄂伦春自治旗| 鸡东县| 乐都县| 鞍山市| 葵青区| 张家口市| 高雄县| 湘乡市| 涟水县| 和硕县| 通榆县| 耒阳市| 温宿县| 湘乡市| 保康县| 景宁| 天水市| 方城县| 大渡口区| 苍溪县| 紫金县| 神农架林区| 汽车| 托克托县| 鄂托克旗| 三原县| 永福县| 吉安县| 牙克石市| 疏附县| 东阳市| 太仆寺旗| 博湖县| 谷城县| 三江| 沾化县| 九龙县| 娄烦县| 长岭县| 桑日县| 玉屏|