溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

發(fā)布時間:2021-08-27 11:01:43 來源:億速云 閱讀:146 作者:小新 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

一、以Web的形式讀取文件

我們創(chuàng)建的演示實例是一個簡單的ASP.NET Core控制臺應(yīng)用,它具有如下圖所示的項目結(jié)構(gòu)。我們可以看到在默認(rèn)作為WebRoot的目錄(wwwroot)下,我們將JavaScript腳本文件、CSS樣式文件和圖片文件存放到對應(yīng)的子目錄(js、css和img)下,我們將把這個目錄的所有文件以Web的形式發(fā)布出來,客戶端可以訪問相應(yīng)的URL來獲取這些文件。

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

針對靜態(tài)文件的請求是通過一個名為StaticFileMiddleware的中間件來實現(xiàn)的,這個中間件類型定義在NuGet包“Microsoft.AspNetCore.StaticFiles”中,所以我們需要預(yù)先按照這個NuGet包。整個應(yīng)用只包含如下所示的這幾行代碼,StaticFileMiddleware這個中間件的注冊是通過調(diào)用ApplicationBuilder的擴展方法UseStaticFiles來完成的。

  public class Program
  {
   public static void Main()
    {
     new WebHostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseKestrel()
       .Configure(app => app.UseStaticFiles())
        .Build()
       .Run();
    }
  }

除了注冊必需的StaticFileMiddleware中間件之外,我們還調(diào)用了WebHostBuilder的UseContentRoot方法將當(dāng)前項目的根目錄作為ContentRoot目錄。我們知道ASP.NET Core應(yīng)用具有兩個重要的根目錄,它們分別是ContentRoot和WebRoot,后者也是對外發(fā)布的靜態(tài)文件默認(rèn)使用的根目錄。由于WebRoot目錄的默認(rèn)路徑就是“{contentroot}/wwwroot”,所示上面這段程序就是將項目中的這個wwwroot目錄下的所有靜態(tài)文件發(fā)布出來。

當(dāng)這個程序運行之后,我們就可以通過向?qū)?yīng)URL發(fā)送HTTP請求的方式來獲取某個的文件,這個URL由文件相當(dāng)于wwwroot目錄的路徑來決定。比如JPG文件“~/wwwroot/img/dophin1.jpg”對應(yīng)的URL為“http://

localhost:5000/img/dophin1.jpg”。我們直接利用瀏覽器訪問這個URL,目標(biāo)圖片會直接顯示出來。

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

上面我們通過一個簡單的實例將WebRoot所在目錄下的所有靜態(tài)文件直接發(fā)布出來。如果我們需要發(fā)布的靜態(tài)文件存儲在其他目錄下呢?依舊是演示的這個應(yīng)用,現(xiàn)在我們將一些文檔存儲在如下圖所示的“~/doc/”目錄下并以Web的形式發(fā)布出來,我們的程序又該如何編寫呢?

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

我們知道ASP.NET Core應(yīng)用大部分情況下都是利用一個FileProvider對象來讀取文件的,它在處理針對靜態(tài)文件的請求是也不例外。對于我們調(diào)用ApplicationBuilder的擴展方法UseStaticFiles方法注冊的這個類型為StaticFileMiddleware的中間件,其內(nèi)部具有一個FileProvider和請求路徑的映射關(guān)系。如果調(diào)用UseStaticFiles方法沒有指定任何的參數(shù),那么這個映射關(guān)系的請求路徑就是應(yīng)用的基地址(PathBase),而FileProvider自然就是指向WebRoot目錄的PhysicalFileProvider。

上述的這個需求可以通過顯式注冊這個映射的方式來實現(xiàn),為此我們在現(xiàn)有程序的基礎(chǔ)上額外添加了一次針對UseStaticFiles方法的調(diào)用,并通過指定的參數(shù)(是一個StaticFileOptions對象)顯式指定了采用的FileProvider(針對“~/doc/”的PhysicalFileProvider)和請求路徑(“/documents”)。

  public class Program
  {
    public static void Main()
    {
     string contentRoot = Directory.GetCurrentDirectory();
      new WebHostBuilder()
        .UseContentRoot(contentRoot)
        .UseKestrel()
       .Configure(app => app
         .UseStaticFiles()
         .UseStaticFiles(new StaticFileOptions {
            FileProvider = new PhysicalFileProvider(Path.Combine(contentRoot, "doc")),
            RequestPath = "/documents"
           }))
        .Build()
       .Run();
    }
  }

按照上面這段程序指定的映射關(guān)系,對于存儲在“~/doc/”目錄下的這個PDF文件(“checklist.pdf”),發(fā)布在Web上的URL為“http://localhost:5000/documents/checklist.pdf”。當(dāng)我們在瀏覽器上請求這個地址時,該PDF文件的內(nèi)容將會按照如下圖所示的形式顯示在瀏覽器上。

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

二、瀏覽目錄內(nèi)容

注冊的StaticFileMiddleware中間件只會處理針對某個具體靜態(tài)文件的額請求,如果我們向針對某個目錄的URL發(fā)送HTTP請求(比如“http://localhost:5000/img/”),得到的將是一個狀態(tài)為404的響應(yīng)。不過我們可以通過注冊另一個名為DirectoryBrowserMiddleware的中間件來顯示請求目錄的內(nèi)容。具體來說,這個中間件會返回一個HTML頁面,請求目錄下的所有文件將以表格的形式包含在這個頁面中。對于我們演示的這個應(yīng)用來說,我們可以按照如下的方式調(diào)用UseDirectoryBrowser方法來注冊這個DirectoryBrowserMiddleware中間件。

  public class Program
  {
   public static void Main()
    {
      string contentRoot = Directory.GetCurrentDirectory();
      IFileProvider fileProvider = new PhysicalFileProvider(
        Path.Combine(contentRoot, "doc"));
      new WebHostBuilder()
       .UseContentRoot(contentRoot)
       .UseKestrel()
       .Configure(app => app
         .UseStaticFiles()
         .UseStaticFiles(new StaticFileOptions {
           FileProvider = fileProvider,
           RequestPath = "/documents"
          })
         .UseDirectoryBrowser()
         .UseDirectoryBrowser(new DirectoryBrowserOptions {
             FileProvider = fileProvider,
             RequestPath = "/documents"
         }))
       .Build()
       .Run();
    }
  }

當(dāng)上面這個應(yīng)用啟動之后,如果我們利用瀏覽器向針對某個目錄的URL(比如“http://localhost:5000/”或者“http://localhost:5000/img/”),目標(biāo)目錄的內(nèi)容(包括子目錄和文件)將會以下圖所示的形式顯示在一個表格中。不僅僅如此,子目錄和文件均會顯示為鏈接,指向目標(biāo)目錄或者文件的URL。

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

三、顯示默認(rèn)頁面

從安全的角度來講,利用注冊的UseDirectoryBrowser中間件顯示一個目錄瀏覽頁面會將整個目標(biāo)目錄的接口和所有文件全部暴露出來,所以這個中間件需要根據(jù)自身的安全策略謹(jǐn)慎使用。對于針對目錄的請求,另一種更為常用的響應(yīng)策略就是顯示一個保存在這個目錄下的默認(rèn)頁面。按照約定,作為默認(rèn)頁面的文件一般采用如下四種命名方式:default.htm、default.html、index.htm或者index.html。針對目標(biāo)目錄下默認(rèn)頁面的呈現(xiàn)實現(xiàn)在一個名為DefaultFilesMiddleware的中間件中,我們演示的這個應(yīng)用可以按照如下的方式調(diào)用UseDefaultFiles方法來注冊這個中間件。

  public class Program
  {
    public static void Main()
    {
      string contentRoot = Directory.GetCurrentDirectory();
      IFileProvider fileProvider = new PhysicalFileProvider(Path.Combine(contentRoot, "doc")); 
      new WebHostBuilder()
        .UseContentRoot(contentRoot)
        .UseKestrel()
        .Configure(app => app
          .UseDefaultFiles()
          .UseDefaultFiles(new DefaultFilesOptions{
            RequestPath = "/documents",
            FileProvider = fileProvider,
          })
          .UseStaticFiles()
         .UseStaticFiles(new StaticFileOptions
          {
            FileProvider = fileProvider,
            RequestPath = "/documents"
          })
          .UseDirectoryBrowser()
          .UseDirectoryBrowser(new DirectoryBrowserOptions
          {
           FileProvider = fileProvider,
           RequestPath = "/documents"
          }))
        .Build()
        .Run();
    }
  }

現(xiàn)在我們在“~/wwwroot/img/”目錄下創(chuàng)建一個名為index.htm的默認(rèn)頁面,現(xiàn)在利用瀏覽器訪問這個目錄對應(yīng)的URL(“http://localhost:5000/img/”),顯示就時這個頁面的內(nèi)容。

怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件

我們必須在注冊StaticFileMiddleware和DirectoryBrowserMiddleware之前注冊DefaultFilesMiddleware,否則它起不了任何作用。由于DirectoryBrowserMiddleware和DefaultFilesMiddleware這兩個中間件處理的均是針對目錄的請求,如果DirectoryBrowserMiddleware先被注冊,那么顯示的總是目錄的內(nèi)容。若DefaultFilesMiddleware先被注冊,在默認(rèn)頁面不存在情況下回顯示目錄的內(nèi)容。至于為什么要先于StaticFileMiddleware之前注冊DefaultFilesMiddleware,則是因為后者是通過采用URL重寫的方式實現(xiàn)的,也就是說這個中間件會將針對目錄的請求改寫成針對默認(rèn)頁面的請求,而最終針對默認(rèn)頁面的請求還得依賴StaticFileMiddleware完成。

DefaultFilesMiddleware中間件在默認(rèn)情況下總是以約定的名稱(default.htm、default.html、index.htm或者index.html)在當(dāng)前請求的目錄下定位默認(rèn)頁面。如果我們希望作為默認(rèn)頁面的文件不能按照這樣的約定命名(比如readme.htm),我們需要按照如下的方式顯式指定默認(rèn)頁面的文件名。

 public class Program
  {
    public static void Main()
    {
      string contentRoot = Directory.GetCurrentDirectory();
      IFileProvider fileProvider = new PhysicalFileProvider(Path.Combine(contentRoot, "doc"));
      DefaultFilesOptions options1 = new DefaultFilesOptions();
      DefaultFilesOptions options2 = new DefaultFilesOptions{
        RequestPath = "/documents",
        FileProvider = fileProvider
     };
     options1.DefaultFileNames.Add("readme.htm");
      options2.DefaultFileNames.Add("readme.htm");
  
      new WebHostBuilder()
        .UseContentRoot(contentRoot)
        .UseKestrel()
        .Configure(app => app
          .UseDefaultFiles(options1)
          .UseDefaultFiles(options2)
          .UseStaticFiles()
          .UseStaticFiles(new StaticFileOptions{
            FileProvider = fileProvider,
            RequestPath = "/documents"
          })
          .UseDirectoryBrowser()
          .UseDirectoryBrowser(new DirectoryBrowserOptions{
            FileProvider = fileProvider,
            RequestPath = "/documents"
          }))
      .Build()
      .Run();
    }
  }

四、映射媒體類型

通過上面演示的實例可以看出,瀏覽器能夠正確的將請求的目標(biāo)文件的內(nèi)容正常的呈現(xiàn)出來。對HTTP協(xié)議具有基本了解的人都應(yīng)該知道,響應(yīng)的文件能夠在支持的瀏覽器上呈現(xiàn)具有一個基本的前提,那就是響應(yīng)消息通過Content-Type報頭攜帶的媒體類型必須與內(nèi)容一致。我們的實例演示了針對兩種類型文件的請求,一種是JPG文件,另一種是PDF文件,對應(yīng)的媒體類型分別是“image/jpg”和“application/pdf”,那么StaticFileMiddleware是如何正確解析出正確的媒體類型的呢?

StaticFileMiddleware針對媒體類型的解析是通過一個名為ContentTypeProvider的對象來實現(xiàn)的,而默認(rèn)使用的則是一個FileExtensionContentTypeProvider對象。顧名思義,F(xiàn)ileExtensionContentTypeProvider是根據(jù)文件的擴展命名來解析媒體類型的。FileExtensionContentTypeProvider內(nèi)部預(yù)定了數(shù)百種常用文件擴展名與對應(yīng)媒體類型之間的映射關(guān)系,所以如果我們發(fā)布的靜態(tài)文件具有標(biāo)準(zhǔn)的擴展名,StaticFileMiddleware就能為對應(yīng)的響應(yīng)賦予正確的媒體類型。

那么如果某個文件的擴展名沒有在這個預(yù)定義的映射之中,或者我們需要某個預(yù)定義的擴展名匹配不同的媒體類型,我們應(yīng)該如何解決呢?還是針對我們演示的這個實例,想在我將“~/wwwroot/img/ dophin1.jpg”這個文件的擴展名改成“.img”,毫無疑問StaticFileMiddleware將能為針對該文件的請求解析出正確媒體類型。這個問題具有若干不同的解決方案,第一種方案就是讓StaticFileMiddleware支持不能識別的文件類型,并為它們設(shè)置一個默認(rèn)的媒體類型,如下所示了具體采用的編程方式。

 public class Program
  {
    public static void Main()
    { 
      new WebHostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory();)
        .UseKestrel()
        .Configure(app => app.UseStaticFiles(new StaticFileOptions {
          ServeUnknownFileTypes = true,
          DefaultContentType   = "image/jpg"
        }))
        .Build()
        .Run();
    }
  }

上述這種解決方案只能設(shè)置一種默認(rèn)媒體類型,如果具有多種需要映射成不同媒體類型的非識別文件類型,采用這種方案就無能為力了,所以最根本的解決方案還是需要將不能識別的文件類型和對應(yīng)的媒體類型進行映射。由于StaticFileMiddleware使用的ContentTypeProvider是可以定制的,我們可以按照如下的方式顯式地為StaticFileMiddleware指定一個FileExtensionContentTypeProvider對象作為它的ContentTypeProvider,然后將取缺失的映射添加到這個FileExtensionContentTypeProvider對象上。

  public class Program
  {
    public static void Main()
    {
      FileExtensionContentTypeProvider contentTypeProvider = new FileExtensionContentTypeProvider();
      contentTypeProvider.Mappings.Add(".img", "image/jpg");
   
      new WebHostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseKestrel()
        .Configure(app => app.UseStaticFiles(new StaticFileOptions{
          ContentTypeProvider = contentTypeProvider
        }))
        .Build()
        .Run();
    }
  }

關(guān)于“怎么使用ASP.NET Core應(yīng)用來發(fā)布靜態(tài)文件”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI