在.NET Maui Blazor中,能否通过HTML5 Video直接播放本地文件系统视频?
问题解答:.NET Maui Blazor中播放用户本地视频文件的可行方案
直接将HTML5 video元素的src指向用户文件系统的绝对路径不可行。
原因分析
.NET Maui Blazor基于WebView运行,遵循浏览器同源安全策略:
- 项目
wwwroot目录下的文件属于应用静态资源,通过相对路径访问时,WebView从应用资源容器加载,属于同源访问,因此可以正常播放。 - 直接使用本地文件系统绝对路径(如
C:\videos\testvideo.mp4)会被WebView安全机制拦截,禁止跨源访问本地文件,避免潜在安全风险。
可行实现方案
要实现用户选择本地视频并播放,需通过FilePicker获取文件,再将文件内容转换为WebView可访问的格式(Base64 Data URI或Object URL)。
方案1:Base64 Data URI(适合小体积视频)
读取视频文件内容并转换为Base64编码,生成Data URI作为video的src:
@page "/videoplayer" @inject IFilePicker FilePicker <h3>本地视频播放器</h3> <video controls width="800" height="462"> <source src="@VideoSource" type="video/mp4" /> 您的浏览器不支持HTML5视频播放。 </video> <button @onclick="PickVideoFile">选择本地视频</button> @code { private string? VideoSource { get; set; } private async Task PickVideoFile() { var pickResult = await FilePicker.PickAsync(new PickOptions { FileTypes = FilePickerFileType.Videos, PickerTitle = "选择MP4视频文件" }); if (pickResult != null) { using var fileStream = await pickResult.OpenReadAsync(); var fileBytes = new byte[fileStream.Length]; await fileStream.ReadAsync(fileBytes, 0, (int)fileStream.Length); // 生成Base64格式的Data URI VideoSource = $"data:video/mp4;base64,{Convert.ToBase64String(fileBytes)}"; } } }
方案2:Object URL(适合大体积视频,节省内存)
通过IJSRuntime将文件流传递给前端,创建Blob Object URL,避免Base64的内存开销:
- 在
wwwroot/js目录下创建video-utils.js脚本:
window.createVideoObjectURL = async (dotNetStream) => { const stream = await dotNetStream.stream(); const videoBlob = new Blob([stream], { type: 'video/mp4' }); return URL.createObjectURL(videoBlob); }; window.revokeVideoObjectURL = (url) => { URL.revokeObjectURL(url); };
- 在
wwwroot/index.html中引用该脚本:
<script src="js/video-utils.js"></script>
- Razor页面代码:
@page "/videoplayer" @inject IJSRuntime JSRuntime @inject IFilePicker FilePicker @implements IDisposable <h3>本地视频播放器</h3> <video controls width="800" height="462"> <source src="@VideoSource" type="video/mp4" /> 您的浏览器不支持HTML5视频播放。 </video> <button @onclick="PickVideoFile">选择本地视频</button> @code { private string? VideoSource { get; set; } private async Task PickVideoFile() { // 先释放之前的Object URL,避免内存泄漏 if (!string.IsNullOrEmpty(VideoSource)) { await JSRuntime.InvokeVoidAsync("revokeVideoObjectURL", VideoSource); } var pickResult = await FilePicker.PickAsync(new PickOptions { FileTypes = FilePickerFileType.Videos, PickerTitle = "选择MP4视频文件" }); if (pickResult != null) { using var fileStream = await pickResult.OpenReadAsync(); var streamReference = new DotNetStreamReference(fileStream); VideoSource = await JSRuntime.InvokeAsync<string>("createVideoObjectURL", streamReference); } } public void Dispose() { // 组件销毁时释放Object URL if (!string.IsNullOrEmpty(VideoSource)) { _ = JSRuntime.InvokeVoidAsync("revokeVideoObjectURL", VideoSource); } } }
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

