ASP.NET Core 6框架揭秘实例演示[29]:搭建文件服务器

通过HTTP请求获取的Web资源很多都来源于存储在服务器磁盘上的静态文件。对于ASP.NET应用来说,如果将静态文件存储到约定的目录下,绝大部分文件类型都是可以通过Web的形式对外发布的。“Microsoft.AspNetCore.StaticFiles” 这个NuGet包中提供了三个用来处理静态文件请求的中间件,我们可以用它们搭建一个文件服务器。[本文节选《ASP.NET Core 6框架揭秘》第18章]

[1901]以Web形式发布文件(图片)(源代码)
[1902]以Web形式发布文件(PDF)(源代码)
[1903]显式文件目录结构(源代码)
[1904]显示目录的默认页面(源代码)
[1905]定制目录的默认页面(源代码)
[1906]设置默认的媒体类型(源代码)
[1907]映射文件扩展名的媒体类型(源代码)

[1901]以Web形式发布文件(图片)

作为演示实例是ASP.NET应用具有如图1所示的项目结构。在默认作为WebRoot的“wwwroot”目录下,我们将JavaScript脚本文件、CSS样式文件和图片文件存放到对应的子目录(js、css和img)下。该目录下的所有文件将自动发布为Web资源,客户端可以访问相应的URL来读取对应它们的内容。

6dfee9d533214c42a1db3fc1134c4d5a.png

图1 静态文件发布的项目结构

针对具体某个静态文件的请求是通过StaticFileMiddleware中间件来处理。如下所示的演示程序中调用IApplicationBuilder接口的UseStaticFiles扩展方法注册的就是这个中间件。

var app = WebApplication.Create();
app.UseStaticFiles();
app.Run();

演示程序运行之后,就可以通过GET请求的方式来读取对应文件的内容,目标文件相对于WebRoot目录的路径就是对应URL的路径,如JPG图片文件“~/wwwroot/img/dolphin1.jpg”对应的URL路径为“/img/dolphin1.jpg”。如果直接利用浏览器访问这个URL,目标图片就会直接以图2所示的形式显示出来。

5b0c3cacb8a04803a36a5004257aef1d.png

图2 以Web形式请求发布的图片文件

[1902]以Web形式发布文件(PDF)

上面通过一个简单的实例将WebRoot所在目录下的所有静态文件发布为Web资源,如果需要发布的静态文件存储在其他目录下呢?比如我们将上面演示的应用程序的一些文档存储在图3所示的“~/doc/”目录下,那么对应的程序又该如何编写呢?

c12683775982e7f535d189b75d71213f.png

图3 发布“~/doc/”和“~/wwwroot”目录下的文件

ASP.NET应用在大部分情况下都是利用一个IFileProvider对象来读取文件的,针对静态文件的读取请求处理也不例外。StaticFileMiddleware中间件内部维护着一个IFileProvider对象和请求路径的映射关系。如果调用UseStaticFiles方法没有指定任何参数,那么这个映射的路径就是应用的基地址(PathBase),采用的IFileProvider对象就是指向WebRoot目录的PhysicalFileProvider对象。上述需求可以通过定制这个映射关系来实现。如下面的代码片段所示,我们在现有程序的基础上额外添加了一次针对UseStaticFiles扩展方法的调用,并利用作为参数的StaticFileOptions配置选项添加请求路径(“/documents”)与对应IFileProvider对象(针对路径“~/doc/”的PhysicalFileProvider对象)之间的映射关系。

using Microsoft.Extensions.FileProviders;var path = Path.Combine(Directory.GetCurrentDirectory(), "doc");
var options = new StaticFileOptions
{FileProvider = new PhysicalFileProvider(path),RequestPath = "/documents"
};var app = WebApplication.Create();
app.UseStaticFiles().UseStaticFiles(options);
app.Run();

按照上面这段程序指定的映射关系,对于存储在“~/doc/”目录下的这个PDF文件(checklist.pdf),请求URL采用的路径就应该是“/documents/checklist.pdf”。如果利用浏览器请求这个地址时,PDF文件的内容就会按照图4所示的形式显示在浏览器上。

064f0b6773cc1de6ce456145482a2f44.png

图4 以Web形式请求发布的PDF文件

[1903]显示文件目录结构

StaticFileMiddleware中间件只会处理针对具体的某个静态文件的请求,如果利用浏览器发送一个针对目录路径的请求(比如“/img”),我们将得到状态为“404 Not Found”的响应。如果希望浏览器呈现出目标目录的结构,就可以注册DirectoryBrowserMiddleware中间件。这个中间件会返回一个HTML页面,请求目录下的结构会以表格的形式显示在这个页面中。我们演示的程序按照如下方式调用IApplicationBuilder接口的UseDirectoryBrowser扩展方法注册了这个中间件。

using Microsoft.Extensions.FileProviders;var path = Path.Combine(Directory.GetCurrentDirectory(), "doc");
var fileProvider = new PhysicalFileProvider(path);var fileOptions = new StaticFileOptions
{FileProvider = fileProvider,RequestPath = "/documents"
};var diretoryOptions = new DirectoryBrowserOptions
{FileProvider = fileProvider,RequestPath = "/documents"
};var app = WebApplication.Create();
app.UseStaticFiles().UseStaticFiles(fileOptions).UseDirectoryBrowser() .UseDirectoryBrowser(diretoryOptions);
app.Run();

当上面的应用启动之后,如果利用浏览器向针对某个目录的URL(如“/”或者“/img”)发起请求,目标目录的内容(包括子目录和文件)就会以图5所示的形式显示在一个表格中。可以看出在呈现的表格中,当前目录的子目录和文件均会显示为链接。

ea92121c0b614442ed39ad26c6e1d630.png

图5 显示目录内容

[1904]显示目录的默认页面

UseDirectoryBrowser中间件会将整个目标目录的结构和所有文件全部暴露出来,所以这个中间件需要根据自身的安全策略谨慎使用。对于针对目录的请求,更加常用的处理策略就是显示一个保存该目录下的默认页面。默认页面文件一般采用如下四种命名约定(default.htm、default.html、index.htm和index.html)。默认页面的呈现实现DefaultFilesMiddleware中间件中,我们演示的这个应用可以按照如下方式调用IApplicationBuilder接口的UseDefaultFiles扩展方法来注册这个中间件。

using Microsoft.Extensions.FileProviders;var path = Path.Combine(Directory.GetCurrentDirectory(), "doc");
var fileProvider = new PhysicalFileProvider(path);var fileOptions = new StaticFileOptions
{FileProvider = fileProvider,RequestPath = "/documents"
};
var diretoryOptions = new DirectoryBrowserOptions
{FileProvider = fileProvider,RequestPath = "/documents"
};
var defaultOptions = new DefaultFilesOptions
{RequestPath = "/documents",FileProvider = fileProvider,
};var app = WebApplication.Create();
app   .UseDefaultFiles() .UseDefaultFiles(defaultOptions).UseStaticFiles().UseStaticFiles(fileOptions).UseDirectoryBrowser().UseDirectoryBrowser(diretoryOptions);app.Run();

下面在“~/wwwroot/img/”和“~/doc”目录下分别创建一个名为index.html的默认页面,并且在该.html文件的主体部分指定一段简短的文字(This is an index page!)。我们在应用启动之后利用浏览器访问这两个目录(“/img”和“/documents”),默认页面就会以图6的形式显示出来。

a402891898e451ee040e5c47ca2f189f.png

图6 显示默认页面

[1905]定制目录的默认页面

我们须将DefaultFilesMiddleware中间件放在StaticFileMiddleware和DirectoryBrowserMiddleware中间件之前。这是因为DirectoryBrowserMiddleware和DefaultFilesMiddleware中间件处理的均是针对目录的请求,如果先注册DirectoryBrowserMiddleware中间件,那么显示的总是目录的结构。如果先注册用于显示默认页面的DefaultFilesMiddleware中间件,那么在默认页面不存在的情况下它会将请求分发给后续中间件,此时DirectoryBrowserMiddleware中间件将当前目录的结构呈现出来。要先于StaticFileMiddleware中间件之前注册DefaultFilesMiddleware中间件是因为后者是通过采用URL重写的方式实现的。这个中间件会将针对目录的请求改写成针对默认页面的请求,而最终针对默认页面的请求还需要依赖StaticFileMiddleware中间件来完成。

2e79308b7778b5ebfaca753819b37767.png

图7 重命名默认页面

DefaultFilesMiddleware中间件在默认情况下总是以约定的名称在当前请求的目录下定位默认页面。如果作为默认页面的文件没有采用这样的约定命名,比如我们如图7所示的方式将默认页面命名为readme.html,就需要按照如下方式显式指定默认页面的文件名(S1905)。

using Microsoft.Extensions.FileProviders;var path = Path.Combine(Directory.GetCurrentDirectory(), "doc");
var fileProvider = new PhysicalFileProvider(path);
var fileOptions = new StaticFileOptions
{FileProvider = fileProvider,RequestPath = "/documents"
};
var diretoryOptions = new DirectoryBrowserOptions
{FileProvider = fileProvider,RequestPath = "/documents"
};
var defaultOptions1 = new DefaultFilesOptions();
var defaultOptions2 = new DefaultFilesOptions
{RequestPath = "/documents",FileProvider = fileProvider,
};defaultOptions1.DefaultFileNames.Add("readme.html"); 
defaultOptions2.DefaultFileNames.Add("readme.html");
var app = WebApplication.Create();
app.UseDefaultFiles(defaultOptions1) .UseDefaultFiles(defaultOptions2).UseStaticFiles().UseStaticFiles(fileOptions).UseDirectoryBrowser().UseDirectoryBrowser(diretoryOptions);app.Run();

[1906]设置默认的媒体类型

通过上面演示的实例可以看出,浏览器能够准确地将请求的目标文件的内容正常呈现出来。对HTTP协议具有基本了解的读者应该都知道,响应文件能够在浏览器上被正常显示的基本前提是响应报文通过Content-Type报头携带的媒体类型必须与内容一致。我们的实例演示了针对两种文件类型的请求,一种是JPG文件,另一种是PDF文件,对应的媒体类型分别是“image/jpg”和“application/pdf”,那么用来处理静态文件请求的StaticFileMiddleware中间件是如何解析出对应的媒体类型的呢?

StaticFileMiddleware中间件针对媒体类型的解析是通过一个IContentTypeProvider对象来完成的, FileExtensionContentTypeProvider是对该接口的默认实现。FileExtensionContentTypeProvider根据文件的扩展命名来解析媒体类型。它在内部预定了数百种常用文件扩展名与对应媒体类型之间的映射关系,所以如果发布的静态文件具有标准的扩展名,StaticFileMiddleware中间件就能为对应的响应赋予正确的媒体类型。

4d91eab6eff9554663b0e60f6fe51f61.png

图8 重命名默认页面

如果某个文件的扩展名没有在预定义的映射之中,或者需要某个预定义的扩展名匹配不同的媒体类型,那又应该如何解决呢?同样是针对我们演示的这个实例,如果我们以图8所示的方式将“~/wwwroot/img/ dolphin1.jpg”文件的扩展名改成.img,那么StaticFileMiddleware中间件将无法为针对该文件的请求解析出正确的媒体类型。这个问题具有若干不同的解决方案,第一种方案就是按照如下方式让StaticFileMiddleware中间件支持不能识别的文件类型,并为设置一个默认的媒体类型。

var options = new StaticFileOptions
{ServeUnknownFileTypes = true,DefaultContentType = "image/jpg"
};
var app = WebApplication.Create();
app.UseStaticFiles(options);app.Run();

[1907]映射文件扩展名的媒体类型

上述解决方案只能设置一种默认媒体类型,如果具有多种需要映射成不同媒体类型的文件类型,这种方案就无能为力了,所以最根本的解决方案还是需要将不能识别的文件类型和对应的媒体类型进行映射。由于StaticFileMiddleware中间件使用的IContentTypeProvider对象是可以定制的,所以可以按照如下方式显式地为该中间件指定一个FileExtensionContentTypeProvider对象,然后将缺失的映射添加到这个对象上即可。

using Microsoft.AspNetCore.StaticFiles;var contentTypeProvider = new FileExtensionContentTypeProvider();
contentTypeProvider.Mappings.Add(".img", "image/jpg");
var options = new StaticFileOptions
{ContentTypeProvider = contentTypeProvider
};var app = WebApplication.Create();
app.UseStaticFiles(options);app.Run();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281671.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【我们一起写框架】C#的AOP框架

原文:【我们一起写框架】C#的AOP框架前言 AOP,大家都是听过的,它是一种面向切面的设计模式。 不过AOP虽然是被称为设计模式,但我们应该很少能看到AOP设计的框架。为什么呢? 因为,AOP单独设计的框架几乎是无法使用的。普…

新浪微博授权认证过程

为什么80%的码农都做不了架构师?>>> 一、授权认证 1、请求用户授权Token URL: https://api.weibo.com/oauth2/authorize HTTP请求方式:GET/POST 请求参数 必选 类型及范围 说明 client_id true string 申请应用时分配的AppKey。 redire…

VisualStudio 使用 FastTunnel 辅助搭建远程调试环境

有时候需要远程调试一些用户问题,期望能使用本机的 Visual Studio 开发环境,调试远程的用户的设备上的应用。这时会遇到的一个问题是如何让本机的 Visual Studio 可以连接上远程的用户的设备,从而进行调试。本文将告诉大家如何采用 FastTunne…

Python1

python介绍python是一种解释型的,面对对象的。带有动态语义的高级程序设计语言python简史1989年,Guido(龟叔)为ABC 语言写的一个插件。因Monty Python的喜剧团体的原因,故给这个语言起名为python。linux也是1989年诞生的,1991年正式发布linux1.0内核;1990年, 发布py…

ncut算法matlab实现,ncut_multiscale_1_6 经典的图像分割算法 的Matlab代码。 238万源代码下载- www.pudn.com...

文件名称: ncut_multiscale_1_6下载收藏√ [5 4 3 2 1 ]开发工具: matlab文件大小: 587 KB上传时间: 2015-04-17下载次数: 4提 供 者: HH详细说明:经典的图像分割算法NCut的Matlab代码。-Matlab code of classic image segmentation algorithm NCut .文件列表(…

使用.NET从零实现基于用户角色的访问权限控制

使用.NET从零实现基于用户角色的访问权限控制本文将介绍如何实现一个基于.NET RBAC 权限管理系统,如果您不想了解原理,可查看推送的另一篇文章关于Sang.AspNetCore.RoleBasedAuthorization[1] 库是使用介绍,直接使用该库即可。背景在设计系统…

数据归一化

数据归一化 数据的标准化是将数据按比例缩放,使之落入一个小的特定区间,一般为0到1之间。在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较…

.NET性能系列文章一:.NET7的性能改进

这些方法在.NET7 中变得更快照片来自 CHUTTERSNAP[1] 的 Unsplash[2]欢迎阅读.NET 性能系列的第一章。这一系列的特点是对.NET 世界中许多不同的主题进行研究、比较性能。正如标题所说的那样,本章节在于.NET7 中的性能改进。你将看到哪种方法是实现特定功能最快的方…

丁洪波 -- 不要“ 总是拿着微不足道的成就来骗自己”

都市快报实盘大赛25期:于海飞/丁洪波荣获冠亚军 七禾网 时间:2010-11-02 12:47:05 来源:期货中国10月30日下午,2010年浙商期货实盘大赛第三季度(都市快报实盘大赛第25期)颁奖典礼在天科大厦浙商期货大会议室…

面试专题(Mysql及Mongodb)

2019独角兽企业重金招聘Python工程师标准>>> mysql面试题 1. 各个数据库存储引擎区别 mysql的存储引擎是针对表进行设置的,一个库的不同表可以设置不同的存储引擎,mysql默认支持多种存储引擎,以适用不同领域的数据库应用需要&…

织梦网站翻页php,dedecms织梦网站列表页和内容页分页样式

织梦分页标签{dede:pagelist istitem"index,pre,next,end,option,info," listsize"5"/},{dede:prenext getpre/},{dede:prenext getnext/}。默认样式和使用模板css样式布局不一样,这时又不想重写样式,我们可以修改织梦标…

KDD走进阿里 数百专家聚集探讨产学研一体化

6月29日,由阿里巴巴集团、中国中文信息学会、KDD China联合主办的数据挖掘前沿发展与未来论坛在杭州举行,会议吸引了来自国际顶级高校和知名企业的近300名专家学者到场参会、近30000人在线观看。论坛除了分享最新的数据挖掘领域最新科研成果及研发思路外…

php模板引擎循环start,PHP模板引擎Smarty内建函数section,sectionelse用法详解

本文实例讲述了PHP模板引擎Smarty内建函数section,sectionelse用法。分享给大家供大家参考,具体如下:section 是 Smarty 模板中除了 foreach 以外的另一种处理循环的方案,section 比 foreach 要灵活,就像是一个改进的 foreach 语句…

OpenHarmony操作系统与龙芯2K1000LA芯片完成适配,龙架构平台获得开源鸿蒙认证

近日,龙芯中科与软通动力控股公司鸿湖万联共同完成OpenHarmony操作系统与龙芯2K1000LA处理器的适配,“乘风1000”开发板(搭载龙芯2K1000LA)荣获OpenHarmony生态产品兼容性证书。至此,万物互联的OpenHarmony生态体系再次…

struts2开发action 的三种方法以及通配符、路径匹配原则、常量

struts2开发action 的三种方法 1、继承ActionSupport public class UserAction extends ActionSupport {// Action中业务处理方法public String login() {System.out.println("UserAction.login()"); // return "success";return SUCCESS;} } 2、实现…

left join 和 inner join

2019独角兽企业重金招聘Python工程师标准>>> left join 和 inner join 首先 MySQL 中 inner join 的效率确实要高于 left join。所以没必要使用 left join 转弯成 inner join 的效果。这样不但效率降低,可读性也会降低。 Number1 select from t1 left j…

Vue3+.NET6,轻松开发管理后台!(可复用)

在GitHub是没找到简单好用的Vue3.NET6管理后台项目,有收藏的请评论区分享。这里分享一套Vue3 Axios TS Vite Element Plus .NET 6 WebAPI JWT SqlSugar的通用管理后台,前后端分离架构,各种最新框架组件,实现了管理后台几乎…

iOS网络请求安全认证(JWT,RSA)

在网络世界中,安全是一个很重要的问题,以往的HTTP请求已经不能承担这个安全任务,抓包工具一抓,你的所有网络请求全都曝光。当然,你可能会采用加密算法来加密数据,但是这仍然不够。 在移动端和服务器的通信过…

linux下mariadb大小写敏感

2019独角兽企业重金招聘Python工程师标准>>> Linux下安装好mariadb后,在使用时会发现mariadb对大小写敏感,这对开发带来一定的不利,这时只要在配置文件中配置一下,取消大小写敏感即可: sudo vi /etc/MySQL/…

评论列表显示及排序,个人中心显示

1.显示所有评论{% for foo in ques.comments %} 2.所有评论排序uquestion db.relationship(Question, backrefdb.backref(comments, order_bycreat_time.desc)) 3.显示评论条数{{ ques.comments|length }} 1题代码如下&#xff1a; <h3>评论区:({{ ques.comments|length…