问题背景:在项目目录下录制了一批mp4视频文件。我通过ip+端口号+MP4的路径返回给api接口调用者。
{
playurl:"localhost:7089/1.mp4",
playurl:"localhost:7089/2.mp4"
playurl:"localhost:7089/3.mp4",
playurl:"localhost:7089/4.mp4"
}
web界面通过视频标签,可以进行页面上的播放,但是就是点击下载的时候,
浏览器会在开启一个tab页面,然后播放视频。视频的右下角有一个下载的功能。再开启一个tab再下载,有点影响用户体验。网上我也搜了前端可以直接处理这种情况,但是前端同事因工作量庞大,没有时间处理,于是鉴于这样的一种情况。我被逼无奈,于是使用后端技术来干预前端。
在自我苦恼纠结中,甚至差点抑郁(夸张了,嘿嘿),使用xiaofeng降龙十八掌大招,我对UseStaticFiles这个静态扩展类做了近一步的研究。
在写WebAPI项目中,会创建一个wwwroot文件夹,在这个里面写一些静态文件。例如html、zip、excel、MP4、json、txt等静态文件。
然后在Configure里面使用静态文件类。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
....
}
....
app.UseStaticFiles();
....
}
用户在浏览器输入 localhost:7089/1.mp4,回车之后,即可在页面上看见一个视频。
有时这个地址需要给第三方的客户使用,会遇到静态文件跨域问题。
此时我们在代码里使用
app.UseCors(
builder => builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
);
是没有效果的,这个app.UseCors 跨域是c# 代码的跨域,我们wwwroot文件夹的文件属于静态代码,这个是控制不了的。
或者用户输入 localhost:7089/1.mp4,是想直接下载,并不想播放。
这个时候,遇到静态文件跨域、静态文件直接下载(输入路径不想在web界面上直接浏览观看)此时就要用到我们UseStaticFiles静态文件高级操作了。
静态文件解决跨域代码如下:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = (c) =>
{
c.Context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
c.Context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, TRACE, HEAD, PATCH");
c.Context.Response.Headers.Add("Access-Control-Allow-Headers", "*");
}
});
如果用户想直接下载MP4、json文件,并不想在线浏览。
地址:localhost:7089/1.mp4
我们可以在地址后面加上后缀,便于我们进行识别过滤。
localhost:7089/1.mp4?f=save
我在路径后面加了?f=save,当用户浏览静态文件时,想下载,我通过这个标识来做判断。当f=save,你可以自定义。例如 download=true等...
静态文件直接下载,上代码:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = (c) =>
{
var request = c.Context.Request;
var response = c.Context.Response;
var f = request.Query["f"].ToString();
if (f.Equals("save", StringComparison.OrdinalIgnoreCase))
{
response.Headers.Add("Content-Disposition", "attachment; filename=" + Path.GetFileName(request.Path));
}
}
});
其实核心代码就是,用户请求我们的地址,我们在响应头部加上 下载的标识,这个"Content-Disposition" 其实是告诉浏览器,我要下载文件,我不想在线浏览。
加完这句话,浏览器输入:localhost:7089/1.mp4?f=save
然后浏览器就会弹出下载的文件。下载的快慢和网络/文件的大小有关系。
如果下载地址有跨域问题,则把上面的代码合在一起就行了。
全部代码如下:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = (c) =>
{
c.Context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
c.Context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, TRACE, HEAD, PATCH");
c.Context.Response.Headers.Add("Access-Control-Allow-Headers", "*");
var request = c.Context.Request;
var response = c.Context.Response;
var f = request.Query["f"].ToString();
if (f.Equals("save", StringComparison.OrdinalIgnoreCase))
{
response.Headers.Add("Content-Disposition", "attachment; filename=" + Path.GetFileName(request.Path));
}
}
});
还有更高级的用法,例如:
运行的netcore代码路径:/root/projectWeb/
linux视频路径:
"/storage/projectWeb/VideoFile/"
Windows视频路径:
"C:\\Users\\autoChang\\Downloads"
我们在上面代码的基础上加一行
RequestPath = new PathString("/VideoFile")
然后对下面的路径做下转换
new PhysicalFileProvider("/storage/projectWeb/VideoFile/"),//这个路径也可以自定义
linux环境整体代码如下:
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider("/storage/projectWeb/VideoFile/"),
OnPrepareResponse = (c) =>
{
c.Context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
c.Context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, TRACE, HEAD, PATCH");
//c.Context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
c.Context.Response.Headers.Add("Access-Control-Allow-Headers", "*");
var request = c.Context.Request;
var response = c.Context.Response;
var f = request.Query["f"].ToString();
if (f.Equals("save", StringComparison.OrdinalIgnoreCase))
response.Headers.Add("Content-Disposition", "attachment; filename=" + Path.GetFileName(request.Path));
},
RequestPath = new PathString("/VideoFile")
});
window环境整体代码如下:
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider("C:\\Users\\98263\\Downloads"),
OnPrepareResponse = (c) =>
{
c.Context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
c.Context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, TRACE, HEAD, PATCH");
//c.Context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
c.Context.Response.Headers.Add("Access-Control-Allow-Headers", "*");
var request = c.Context.Request;
var response = c.Context.Response;
var f = request.Query["f"].ToString();
if (f.Equals("save", StringComparison.OrdinalIgnoreCase))
response.Headers.Add("Content-Disposition", "attachment; filename=" + Path.GetFileName(request.Path));
},
RequestPath = new PathString("/VideoFile")
});
通过netcore运行的ip+端口号+路径 也可以访问视频的地址:
localhost:7089/VideoFile/1.mp4
好了,本期分享就到这里吧~