在.NET Framework時代,我們可以利用IIS設定虛擬目錄,如此就可以讀取網站目錄外,存在其他地方的檔案
這種行為通常會用在一些非專案的外部檔案或上傳檔案的目錄,以維持網站專案目錄的純淨性
那到了NET Core不能再在IIS設定虛擬目錄了,所以要改用其他方式設定
我這邊已經在News2寫好了一個上傳檔案,這邊可以下載範例檔,我就不操作這部分了
var folderPath = Path.Combine(@"d:\kcgupload", "news2");
var filePath = Path.Combine(folderPath, update.NewsId + ".jpg");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
using (var stream = new FileStream(filePath, FileMode.Create))
{
await news.File.CopyToAsync(stream);
}
這邊上傳到d:\kcgupload
接著我們要將以下位置的圖片,替換成上傳的圖片

但是今天是在d:\kcgupload,我們該如何讀取這個外部資料夾的檔案呢?
首先先到program.cs來做設定
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(builder.Configuration.GetValue<string>("OutsidePhysicalFile")),
RequestPath = "/kcgupload",
});
這邊我們會習慣把設定路徑內容寫在appsettings.json跟appsettings.Development.json
因為我們上線區跟開發區的路徑有很大的機率會不一樣
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"KcgDatabase": "Server=localhost;Database=Kcg;TrustServerCertificate=true;Trusted_Connection=True;"
},
"OutsidePhysicalFile": "D:\\kcgupload"
}
經過以上的設定後,我們專案網站在讀/kcgupload的網址時,就會是讀你D:\kcgupload
接著我們到圖片的html去做修改圖片的src
<div class="ImageZone">
<img src="/kcgupload/news2/@(Model.NewsId).jpg" loading="lazy">
<div class="dateZone">
<span>@Model.StartDateTime.ToString("yyyy-MM-dd")</span>
</div>
</div>
就可以發現我們順利的讀到圖片了

但這裡還有兩個需要修改的地方,第一個就是
var folderPath = Path.Combine(@"d:\kcgupload", "news2");
我們不應把路徑寫死在程式裡,這時候我有兩個選擇
第一種寫在appsettings.json裡去取用,第二種使用IFileProvider,在使用IFileProvider取得路經目錄位置
因為我們要配合第二個需要修改的地方,所以這邊我們使用IFileProvider的方式處理
先一樣到program.cs依賴注入該服務
builder.Services.AddSingleton<IFileProvider>(new PhysicalFileProvider(builder.Configuration.GetValue<string>("OutsidePhysicalFile")));
接著在程式中取得該服務
public class News2Controller : Controller
{
private readonly IFileProvider _fileProvider;
public News2Controller(IFileProvider fileProvider)
{
_fileProvider = fileProvider;
}
}
接著用服務取得該實體目錄位置
var folderPath = _fileProvider.GetFileInfo("news2").PhysicalPath;
如此可以試試看有沒有正常運作
當然如果這邊單純讀取不需要使用到IFileProvider,但配合下一節會使用到,所以這個先用這樣子寫
範例檔:下載