ASP.NET MVC 向瀏覽器發送文件以提供文件下載功能


     撐到大三了,結果發現周圍的同學更加墮落了,尤其是某些人,表面上看起來很認真,實際上三天打魚,兩天曬網,結果一事無成,卻還要抱怨學校教育失敗。

     為了吸取他們的教訓,就算是一個小小的編碼問題,我也要努力解決。因為學習的機會一向都在,只是自己有沒有去努力而已。

     之前做個班級站點的課程設計,用一天半的時間做完雖然各方面不咋樣,但麻雀雖小,五臟俱在,功能流程還是挺完整的。

     就算是一個小小的課程設計,在這短暫的時間內,也遇到了不少問題,有大有小。

     先說文件下載這塊。

     文件下載一般都是需要一個文件選擇對話框來選擇存放文件的地方。我們可以自己做一個,但簡單的方面就是利用瀏覽器的現成功能。

     所有的瀏覽器都包括文件下載功能,但文件選擇對話框卻不是每個瀏覽器都有提供。這里我只選擇我常用的兩個瀏覽器:谷歌瀏覽器和搜狗瀏覽器。

     先來一個小例子:

public ActionResult Index()
{
     var path = Server.MapPath("~/frog.jpg.jpg");
     return File(path, "iamge/jpeg");
}

     這里是下載工程根目錄下的frog.jpg.jpg。
     代碼非常簡短,只有兩行,但效果卻不差:

      

      這是搜狗瀏覽器上的效果,如果是谷歌瀏覽器,則是直接下載下來,但是文件並不是我們的文件名,甚至格式也不一樣,就是一個奇怪的名為"下載"的文件。

      首先是解釋上面兩行代碼的原理:

      Server.MapPath()的參數是一個虛擬路徑的,它的原理是根據提供的虛擬路徑返回一個虛擬路徑對應的物理路徑,而且參數路徑必須是虛擬路徑。我們服務器上傳的文件都是放在服務器的一個路徑下,這個路徑是物理路徑,但是打開文件的URL卻是虛擬路徑,這樣的好處就像是相對路徑和絕對路徑的對比,想想如果我們將文件的額存放地點放在另一個地方,如果URL為物理路徑,那么就會找不到該文件。

      path現在是frog.jpg.jpg的物理路徑,然后我們要將該文件發送給瀏覽器,則需要利用FilePathResult的File(),指定發送文件的物理路徑和格式就可以了。

      值得注意的是,如果是在搜狗中,指定格式是application/x-zip-compressed(zip的MIME格式)或者application/octet-stream(rar的MIME格式),在網頁上看到的將會是亂碼,但如果是谷歌,依然是上面那樣的情況,但是用壓縮文件軟件打開,就會發現里面就是我們要的文件,它確實是被下載下來了。

      由於谷歌瀏覽器的行為與我們想要的效果差了太遠了,所以下面就不再討論谷歌瀏覽器的行為。

      我用word文檔,Excel表格和txt文檔格式的文件分別發送給瀏覽器,結果只有txt文檔的文件中的內容能夠正常顯示在網頁中,其他都是亂碼,可見,網頁能夠直接打開的文件格式是有限的,至少需要第三方軟件打開的文件是無法打開的。

      上面這些都不是重點,只是我的一點好奇心而已。現在我們進入重點,就是讓瀏覽器提供下載對話框。

      要實現這樣的功能,上面的代碼是不行的,至少我這邊是不行的,要用下面的代碼: 

var path = Server.MapPath("~/1.txt");
var name = Path.GetFileName(path);
return File(path, "application/zip-x-compressed", name);

      然后瀏覽器的運行效果如:

  

     這就是我們想要的結果。

     我們增加了一行代碼,就是使用Path.GetFileName()來獲取指定物理路徑的文件的文件名和擴展名,然后再在File()中增加一個新的參數,該參數就是我們要下載的文件的文件名和擴展名。

      但可怕的是,上面代碼中File的格式可以隨便指定,甚至可以直接為"1"(只要不是null以及""),都會提供上面的下載對話框!!這告訴我們,該下載對話框需要的並不是文件的正確格式,它需要的僅僅只是需要下載的文件的文件名(這個文件名並一定要是正確的文件名,我們可以指定新的名字,反正它就只要將該物理路徑下的那個文件下載下來就行)以及該文件的物理路徑。

   必須注意的是,如果文件名包含有中文,那么它就會顯示這樣的效果:

        如果想要顯示正確的中文文件名,我們可以這樣做:

return File(path, "1", Url.Encode(name));

        效果就會這樣:

       

   要實現上面的效果,我們還可以這樣做:
byte[] data = Encoding.UTF8.GetBytes("~/中國.txt");
return File(data, "1", Url.Encode("中國.txt"));

      這里我們是直接將"~/中國.txt"變為byte[]數組然后發給瀏覽器,保存在中國.txt中,打開就是"~/中國.txt"。這種方式屬於FileContentResult。

      大概的內容就是上面這樣,當然我們可以自定義,畢竟像是谷歌瀏覽器根本就不提供下載對話框的情況下,更加需要我們自定義下載對話框,但這里不講,先是這樣,以后再繼續補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM