将视频分块流式传输到客户端

Jaa*_*aap 7 c# webassembly asp.net-core blazor

信息:(HTTP/2) Kestrel 托管 Blazor WASM ASP.NET Core 6 预览版 1 / C# 9 项目。

我编写了下面的代码,将视频文件以(实际物理)单独的块的形式从服务器传输到客户端,以防止普通用户在(例如)浏览器的开发工具中一键下载视频。

它实际上有效(请参见代码片段下面的屏幕截图)并且搜索也有效,但我想知道我是否做得正确。我希望我可以使用 SO 来实现这一点,但实际上我正在寻找有关我的代码的帮助、建议和/或评论。过去两周我一直在研究这个代码块,搜索代码片段,阅读文档/博客,现在我终于有了一些有用的东西,但也许我做错了,或者也许我忘记了一些真正重要的东西。这个代码规模是否是我的问题之一。我是否using正确使用了声明?无论如何,代码看起来没问题吗:)

仅供参考:我知道该enableRangeProcessing参数,但据我所知,这在这种情况下不适用。寻求确实有效。

/服务器/控制器/StreamController.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Media.Server.Controllers
{
    [Route("[controller]")]
    public class StreamController : ControllerBase
    {
        private readonly IWebHostEnvironment env;
        private readonly ILogger<StreamController> logger;
        public StreamController(ILogger<StreamController> logger, IWebHostEnvironment env)
        {
            this.logger = logger;
            this.env = env;
        }

        [HttpGet("{file}")]
        public async Task GetStream(string file)
        {
            var provider = new PhysicalFileProvider(env.ContentRootPath);
            string videoPathFile = Path.Combine(provider.Root, "Files", "Videos", $"{file}");
            byte[] buffer = new byte[1024 * 1024 * 4]; // 'Chunks' of 4MB
            long startPosition = 0;

            if (!string.IsNullOrEmpty(Request.Headers["Range"]))
            {
                string[] range = Request.Headers["Range"].ToString().Split(new char[] { '=', '-' });
                startPosition = long.Parse(range[1]);
            }

            using FileStream inputStream = new(videoPathFile, FileMode.Open, FileAccess.Read, FileShare.Read)
            {
                Position = startPosition
            };
            int chunkSize = await inputStream.ReadAsync(buffer.AsMemory(0, buffer.Length));
            long fileSize = inputStream.Length;

            if (chunkSize > 0)
            {
                Response.StatusCode = 206;
                Response.Headers["Accept-Ranges"] = "bytes";
                Response.Headers["Content-Range"] = string.Format($" bytes {startPosition}-{fileSize - 1}/{fileSize}");
                Response.ContentType = "application/octet-stream";

                using Stream outputStream = Response.Body;
                await outputStream.WriteAsync(buffer.AsMemory(0, chunkSize));
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(部分)客户端.razor代码

<video id="videostream" poster="@videoPoster" class="videostyle" oncontextmenu="return false;" controls disablePictureInPicture controlsList="nodownload">
    <source src="/Stream/@videoFileName" type="@ContentType;codecs=@Codecs" />
    Your browser does not support the video tag.
</video>
Run Code Online (Sandbox Code Playgroud)

DevTools 网络窗格的屏幕截图

开发工具截图