.NetCore之下載檔案

神牛003發表於2017-09-25

本篇將和大家分享的絲.NetCore下載檔案,常見的下載有兩種:A標籤直接指向下載檔案地址和post或get請求後臺輸出檔案流的方式,本篇也將圍繞這兩種來分享;如果對您有好的幫助,請多多支援。

  • 允許站點不識別content-type下載檔案(即:不受mime型別限制下載)
  • 如何允許下載.nupkg和.apk字尾的檔案
  • Razor模板的post下載檔案例子
  • 半年來使用NetCore的一些感想和焦慮

允許站點不識別content-type下載檔案(即:不受mime型別限制下載)

對於netcore的web專案而言,內建了一些content-type允許下載的檔案型別;我們將通過一個普通的razorweb專案來看看直接通過連線下載excel例子;首先,在專案的wwwroot目錄建立一個bak資料夾,然後在該目錄下存放如下幾種檔案:

然後不用修改任何程式碼或設定,直接啟動站點,再直接在瀏覽器位址列分別錄入下載檔案地址,如:

http://localhost:1120/bak/excel.xls

http://localhost:1120/bak/love.apk

http://localhost:1120/bak/stackexchange.redis.1.2.6.nupkg

http://localhost:1120/bak/Startup.cs

通過測試這個時候只有excel.xls檔案是能直接被下載的,其他的都是404:

要想.apk,.nupkg.cs等字尾的檔案不被限制,我們可以通過 public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, StaticFileOptions options); 擴充套件來設定,我們僅僅只需要修改為如下程式碼:

            app.UseStaticFiles(new StaticFileOptions
            {
                //設定不限制content-type
                ServeUnknownFileTypes = true 
            });

然後在重啟執行,這個時候我們再來訪問下載這幾個檔案就沒問題了(注意這個時候下載任何字尾的檔案都行),如下截圖:

至於cs字尾的檔案在google瀏覽器中是直接顯示的內容,這裡就不貼圖了,有興趣的可以試試;

如何允許下載.nupkg和.apk字尾的檔案

通過上面例子我們能夠使用 ServeUnknownFileTypes = true; 直接設定無限制下載檔案型別,這種通常不是太好或者說不允許,亦或者不常說的不安全吧;如果我們只需要增加.nupkg和.apk字尾的檔案的下載,那麼可以通過如下程式碼來新增mime型別,如:

app.UseStaticFiles(new StaticFileOptions
            {
                //ServeUnknownFileTypes = true 
                ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
                {
                    { ".apk","application/vnd.android.package-archive"},
                    { ".nupkg","application/zip"}
                })
            });

同樣的也能對excel,apk,nupkg字尾的檔案進行下載:

但是這個時候我們訪問 http://localhost:1120/bak/Startup.cs 就得不到下載的內容了:

因為我們沒有新增對.cs檔案的擴充套件型別,故而系統直接給咋們返回404;這裡我們通過FileExtensionContentTypeProvider物件的建構函式傳遞了一個mapping的dic型別來讓專案知道允許下載的content-type型別的檔案;

Razor模板的post下載檔案例子

老實說最近一端時間有空我就會研究下Razor模板,下面我們將通過她的post表單的方式來請求後端下載檔案的方法;下面直接給出login.cshtml檔案的程式碼:

@page
@model LoginModel
@{}
<form method="post">
    <button type="submit" asp-page-handler="down" class="btn">下載</button>
    <button type="submit" asp-page-handler="down01" class="btn">下載01</button>
    <button type="submit" asp-page-handler="down02" class="btn">下載02</button>
</form>

這裡值得注意的是,razor通過asp-page-handler=來執行請求後端的方法,我們來看看最終她生成的html程式碼後是什麼樣子的:

能夠看出這裡主要通過handler作為引數名稱來傳遞請求的後端方法,下面再來看看後端程式碼這樣寫的(為了方便下載檔案的路勁我以love.apk為例):

/// <summary>
        /// 虛擬檔案地址輸出下載
        /// </summary>
        /// <returns></returns>
        public IActionResult OnPostDown()
        {
            var addrUrl = "/bak/love.apk";
            return File(addrUrl, "application/vnd.android.package-archive", Path.GetFileName(addrUrl));
        }
        
        /// <summary>
        /// 檔案流的方式輸出
        /// </summary>
        /// <returns></returns>
        public IActionResult OnPostDown01()
        {
            var addrUrl = @"D:\F\學習\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\bak\love.apk";
            var stream = System.IO.File.OpenRead(addrUrl);
            return File(stream, "application/vnd.android.package-archive", Path.GetFileName(addrUrl));
        }

        /// <summary>
        /// 通過HttpClient獲取另外站點的檔案流,再輸出
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> OnPostDown02()
        {
            var path = "https://files.cnblogs.com/files/wangrudong003/%E7%89%B9%E4%BB%B701.gif";
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(path);
            var stream = await client.GetStreamAsync(path);
            return File(stream, "application/vnd.android.package-archive", Path.GetFileName(path));
        }

後端3個post接受方法都同樣使用了FileStreamResult來輸出下載檔案,不同點在於檔案來源不同;

對於簡單一些的站點來說,下載檔案一般存在於站點目錄下,有點類似於我這裡的wwwroot/bak目錄,因此能夠通過站點虛擬目錄下載,也就是咋們第一種的下載方式;

有一些站點為了檔案安全性,一般會存在於web站點的相同伺服器磁碟中,因此需要通過這裡的第二種方式獲取檔案流,再傳遞給File();

最後一種就是把自己其他站點或者別人站點上的檔案轉一下,當做自己的檔案來輸出,這種方式也就是咋們常說的盜鏈方式之一

對於razor的handler引數,這裡需要注意的是她對應是咋們後端程式碼OnGetxxx或者OnPostxxx方法中的xxx名稱,這是一種razor請求規範,必須要遵守哦。

半年來使用NetCore的一些感想和焦慮

感想:

到目前netcore最新版本2.0,其api很強大了,就目前我做的幾個專案使用來看,她api支援度很好;之前遇到過也有人問過我有處理圖片的api嗎,答案是肯定的,現在nuget包社群已經有很多種包支援圖片處理了,有興趣的朋友可以去看看https://www.nuget.org/packages;在穿插了幾個專案後,深刻感覺netcore的學習成本其實並不高,就netcore的mvc專案而言,只要之前會mvc框架,或是webform(個人感覺對應razor)那用起來是無壓力;這裡建議有些不敢嘗試netcore2.0的朋友或者覺的有學習成本的朋友不妨試試;netcore官網文件:https://docs.microsoft.com/en-us/aspnet/core/

焦慮:

netcore2.0出來還是有段時間了,這段時間儘管有很多朋友在部落格園分享很多相關的文章和git上的專案;但是在3個netqq群中反應或者提出netcore開發遇到的問題情況來看還是很少,不由讓人擔心;當然了我所知道的幾個大牛們或公司的部分技術決策層的人也在關注並也陸續用這再做新專案;其他城市我不瞭解,就北京這邊很有一些創業公司的創業專案起始點就用的是netcore,所以希望還在觀望的朋友或領導們是時候開始行動了,一起努力推動社群的發展。

相關文章