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,一经查实,立即删除!

相关文章

js 栈(进制转换)

<!DOCTYPE html>Documentposted 2017-12-07 19:33 mysure 阅读(...) 评论(...) 编辑 收藏 刷新评论刷新页面返回顶部转载于:https://www.cnblogs.com/ar13/p/8000718.html

流程展示 php,js实现动态的流程进度展示条

这次给大家带来js实现动态的流程进度展示条&#xff0c;js实现动态流程进度展示条的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。一、设计思路分为以下几步(仅供参考)【竖线线】这个采用ul的list标签制作&#xff0c;保证了可随时添加&#xff0c;以…

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

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

新浪微博授权认证过程

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

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

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

深入理解null的原理

--null的原理 --oracle一直将null和空字符串’’<长度为0>同等对待<如’’ is null是true,’’null为false,如果声明a varchar2:’’,那么a is null为true,a’’为false>--1.null的运算 --算术表达式和null 运算总为null,实际上所有的操作符除了||连接操作符外&…

阻止中文输入法输入拼音的时候触发input事件

阻止中文输入法输入拼音的时候触发input事件 前言 最近看element-ui源码的时候看到el-input发现的。这个少见的事件。 compositionstart、compositionend事件&#xff08;MDN解释) compositionstart事件触发于一段文字的输入之前&#xff08;类似于 keydown 事件&#xff0c;但…

Python1

python介绍python是一种解释型的&#xff0c;面对对象的。带有动态语义的高级程序设计语言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详细说明&#xff1a;经典的图像分割算法NCut的Matlab代码。-Matlab code of classic image segmentation algorithm NCut .文件列表(…

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

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

数据归一化

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

vi is failed with error E382: Cannot write, 'buftype' option is set in Linux

在linux下生成jar文件遇到了编码问题&#xff0c;于是想vi t.jar&#xff0c;在保存是报错&#xff1a;E382: Cannot write, buftype option is set 解决方法&#xff1a; 可以用下面的命名查看buftype的设置&#xff0c;当buftypenofile时&#xff0c;不能保存文件&#xff0c…

列表生成式的使用

输入&#xff1a;[Hello, World, 18, Apple, None] 输出&#xff1a;[hello, world, apple] L [Hello, World, 18, Apple, None] print([w.lower() for w in L if isinstance(w, str)])# -- coding: utf-8 -- L [Hello, World, 18, Apple, None] L2 [] L2 [w.lower() for w…

matlab 12位 显示不出来,求助大神,为何不同机器运行MATLAB结果不同

求助&#xff1a;不同机器运行MATLAB结果不同我调用MATLAB优化工具箱的库函数fmincon&#xff0c;使用相同的初始解(可行解)&#xff0c;对同一个问题进行局部搜索(算法为序列二次规划&#xff0c;即SQP)&#xff0c;但在不同机器上得到的结果不同。一共有五台机器 (为了方便&a…

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

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

UVA - 10061 How many zero#39;s and how many digits ?

n!x*b^y, 当x为正整数时,最大的y就是n!末尾0的个数了, 把n,b分别拆成素因子相乘的形式: 比如, n5,b16 n5,b2^4, 非常明显,末尾0的个数为0 10进制时,n!a*10^x b进制时,n!c*b^y 非常明显,n!的位数就是最大的x1 这里计算我用了log,精度设置为1e-9 #include<iostream> #inclu…

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

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

面试专题(Mysql及Mongodb)

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

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

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

通过中间件添加用户的Claim

本文主要介绍 Sang.AspNetCore.RoleBasedAuthorization[1] 库如何通过中间件实现对用户 Claim 的添加。背景前面我们介绍了通过对自定义授权策略和自定义授权处理程序的使用实现了基本的RBAC权限设计&#xff0c;将大量的用户可访问资源及操作的标识直接放到用户的 JWT Token 中…