diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadAvatar.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadAvatar.razor deleted file mode 100644 index fac95fa7e80d2c0c9e8408848f9b4528fb85fb24..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadAvatar.razor +++ /dev/null @@ -1,117 +0,0 @@ -@inject IStringLocalizer Localizer -@inject ToastService ToastService -@implements IDisposable - -
-
-

@Localizer["AvatarUploadTips1"]

- -
-
-

@Localizer["AvatarUploadTips2"]

- -
-
-

@((MarkupString)Localizer["AvatarUploadTips3"].Value)

- -

@((MarkupString)Localizer["AvatarUploadTips5"].Value)

-

- -
-
-

@((MarkupString)Localizer["AvatarUploadTips6"].Value)

- -
-
-

@((MarkupString)Localizer["AvatarUploadTips7"].Value)

- -
-
- -
-
- -
-
- -
-
-
-
-
- - -@code { - /// - /// Dispose - /// - public void Dispose() - { - ReadAvatarToken?.Cancel(); - GC.SuppressFinalize(this); - } - - private static long MaxFileLength => 200 * 1024 * 1024; - - private Person Foo { get; set; } = new Person(); - - private List PreviewFileList { get; } = new(new[] { new UploadFile { PrevUrl = "./images/Argo.png" } }); - - [NotNull] - private ConsoleLogger? Logger { get; set; } - - private CancellationTokenSource? ReadAvatarToken { get; set; } - - private async Task OnAvatarUpload(UploadFile file) - { - // 示例代码,使用 base64 格式 - if (file != null && file.File != null) - { - var format = file.File.ContentType; - if (CheckValidAvatarFormat(format)) - { - ReadAvatarToken ??= new CancellationTokenSource(); - if (ReadAvatarToken.IsCancellationRequested) - { - ReadAvatarToken.Dispose(); - ReadAvatarToken = new CancellationTokenSource(); - } - - await file.RequestBase64ImageFileAsync(format, 640, 480, MaxFileLength, ReadAvatarToken.Token); - } - else - { - file.Code = 1; - file.Error = Localizer["UploadsFormatError"]; - } - - if (file.Code != 0) - { - await ToastService.Error(Localizer["UploadsAvatarMsg"], $"{file.Error} {format}"); - } - } - } - - private static bool CheckValidAvatarFormat(string format) - { - return "jpg;png;bmp;gif;jpeg".Split(';').Any(f => format.Contains(f, StringComparison.OrdinalIgnoreCase)); - } - - private Task OnAvatarValidSubmit(EditContext context) - { - Logger.Log(Foo.Picture?.Name ?? ""); - return Task.CompletedTask; - } - - private class Person - { - [Required] - [StringLength(20, MinimumLength = 2)] - public string Name { get; set; } = "Blazor"; - - [Required] - [FileValidation(Extensions = new string[] { ".png", ".jpg", ".jpeg" }, FileSize = 50 * 1024)] - public IBrowserFile? Picture { get; set; } - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadBase64.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadBase64.razor deleted file mode 100644 index 347cf6586cc6a65337a50a8cd4ba78889f1c5a31..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadBase64.razor +++ /dev/null @@ -1,8 +0,0 @@ - - -@code { - private List Base64FormatFileList { get; } = new List() - { - new UploadFile { FileName = "Test", PrevUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAkCAYAAAD/yagrAAAE60lEQVR4AWJwL/AB9GIWvI0jURz/L1NomZmZP8p9kWNmhnIbKPdomZmZGcJgO7QsWMbce55Yl11t47FbVdKTYpjOr/+H4y4Z/MpYeJVV8KVvokFRylq9osKfVtGQ/NHyPl2CbNVGwau2oOlmgUDJtDJGzxtvvIA3vRH+7IgeA0VtYhQBtKPlToFgC6RY58aggfwLNKhr0Zry2NnPrpIM2YGW2+UBG1IEmdGVJEVXE+hQXt8joKhLjdGVZHd7TSD9DHmT3J1dheroSF4fhnvUVQwbZx9UOnHSzQjkTN0tIG+8hFdbxet4PQOG4WqJwN1hFVb+xUBmCblxvxRkIE+Q+Yf0T31NSrp4/RV4FhHgoSTchQRZBK4D1+Fe2q2g8CYXU6buQyNDaiZKZhn0IYXHVwbkRQydHyawOAGGisa/o3DvI/jF3QKKiuAy+LKs5CvaXMLdeXb35wbkKTjmReDZHysCBosWJqN7r0jZ/VfgXtIlUNQnVpK7D4nNJSC5BHGi1d108Ppr8MxlF0cJqBSyFJaUfUnvHLyO4cttgaI+NhGB7HE0MaSUks/gU5vwe1gv5tfhmUmAhxME8jbIUtiEDus+fhmDJlgCRY0ylZRZhybKWtNinmYlH9NvL5puO3m9UHOkgzb3xuF5HCkDyhYiSwrYVfQPTpYChTc+E35tG9VJBjGFFNmtVlNMDnjzbx0EBpKq1eTeh2awbArBRuHadBWu6WVB4U/NITfuobYoCZl7QL//wDtr+nTmsgzQh2Kwgtz7QAZWFeGw/RI8s94Kigp1PvzZg2i9x11FDtKn/oZCoZdZxhaAXmG4/ohJKHudLE1Gyu66DOfs10BRR5CU3TKQIrtzj9BAkF991dsMslTZEClLsI+jFmANZYFAdAJl9QG03jWH9GrcFh9QTP4Of6GfJGSpsv1J2aoEKRuWCANNJNqOFAaPAW36rVRMCjVf6ZCtqYF2p6Asxg5mWK6tQamY9RCs8z1wF+FxTR5UqYT/3GC7oCkMHcjxKguq6cnl+Egf2whip3C9Yu56jk+GXXOtv1XIa8L1f3AFkHe9az83AmNanwV/bhfa5JKJ3n1slCUL8dk7CNfvVFMfySRThoxbK7fh18tTZXI2QeySLk88IRGsbHkqQj6wUJ72G5CloCXKZrdbLPgVMgVfQMq5m97bfQWOOeVbaK02nSA2ofn2y662UJE47horLZTe38oDjdxQUhmawocxa0OJ5hXjnZE4w1y0uc/iULKGfk+xNuZxI/BnjhFs+THPq4phmTsbeYPXRjFsJJ+NSMlnInHkxrwzGDjR3uBcG1/B/b/TwZkhubb6tP2oVfTAD2G4kw9vYiA2h+zy4GwYxd7S4qGOgd6oqVn6re1DTXiO4e4wPF+yQlF4ZCBfheSPIjJn+ciS/w93qjA6aZYqeQ5D3dTqvuE6GZNTkov5vqsYvLh7j8u1sWWkLIdBQR+q+XdtaKGhJCWBDpkwgSw9gRpKyoNKw6rjCLCDP4yVflSgWFwt3C0HSUo2BTFYX28fVAaWPpDx7wtwjOSSUszawnUT0KTudlfrFQwZ3WNf867CNZQhk/C8kIFUhJLt/O3Jzn62IYNwrUvA8zws4W61CGlDSfugXMz5pJgiSFYyXMYiRXdH4GmyqaR9UHLxzxG41KAwpZxRPN4kRf85Z5I4MvYfFUFGfemJG40AAAAASUVORK5CYII=" }, - }; -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadClickUpload.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadClickUpload.razor deleted file mode 100644 index 3e14a3560c1a344b5a7a1efe53e93ac6e640704f..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadClickUpload.razor +++ /dev/null @@ -1,89 +0,0 @@ -@inject IStringLocalizer Localizer -@inject ToastService ToastService -@inject IOptionsMonitor SiteOptions -@implements IDisposable - -
-
-

@((MarkupString)Localizer["UploadClickUploadTips1"].Value)

- -
-
-

@((MarkupString)Localizer["UploadClickUploadTips2"].Value)

- -

@((MarkupString)Localizer["UploadClickUploadTips3ShowUploadList"].Value)

- - -@code { - /// - /// Dispose - /// - public void Dispose() - { - ReadToken?.Cancel(); - GC.SuppressFinalize(this); - } - - private static readonly Random random = new(); - - private async Task OnClickToUpload(UploadFile file) - { - // 示例代码,模拟 80% 几率保存成功 - var error = random.Next(1, 100) > 80; - if (error) - { - file.Code = 1; - file.Error = Localizer["UploadsError"]; - } - else - { - await SaveToFile(file); - } - } - - private async Task OnClickToUploadNoUploadList(UploadFile file) - { - await ToastService.Success("Upload", $"{file.OriginFileName} uploaded success."); - } - - private CancellationTokenSource? ReadToken { get; set; } - - private static long MaxFileLength => 200 * 1024 * 1024; - - private async Task SaveToFile(UploadFile file) - { - // Server Side 使用 - // Web Assembly 模式下必须使用 webapi 方式去保存文件到服务器或者数据库中 - // 生成写入文件名称 - var ret = false; - if (!string.IsNullOrEmpty(SiteOptions.CurrentValue.WebRootPath)) - { - var uploaderFolder = Path.Combine(SiteOptions.CurrentValue.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader"); - file.FileName = $"{Path.GetFileNameWithoutExtension(file.OriginFileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(file.OriginFileName)}"; - var fileName = Path.Combine(uploaderFolder, file.FileName); - - ReadToken ??= new CancellationTokenSource(); - ret = await file.SaveToFileAsync(fileName, MaxFileLength, ReadToken.Token); - - if (ret) - { - // 保存成功 - file.PrevUrl = $"images/uploader/{file.FileName}"; - } - else - { - var errorMessage = $"{Localizer["UploadsSaveFileError"]} {file.OriginFileName}"; - file.Code = 1; - file.Error = errorMessage; - await ToastService.Error(Localizer["UploadFile"], errorMessage); - } - } - else - { - file.Code = 1; - file.Error = Localizer["UploadsWasmError"]; - await ToastService.Information(Localizer["UploadsSaveFile"], Localizer["UploadsSaveFileMsg"]); - } - return ret; - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFileIcon.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFileIcon.razor deleted file mode 100644 index 9ea06a4d12ff20b01f40d0a2f2526b9b6ac3b11b..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFileIcon.razor +++ /dev/null @@ -1,90 +0,0 @@ -@inject IStringLocalizer Localizer -@inject ToastService ToastService -@inject IOptionsMonitor SiteOptions -@implements IDisposable - - - -@code { - /// - /// Dispose - /// - public void Dispose() - { - ReadToken?.Cancel(); - GC.SuppressFinalize(this); - } - - private List DefaultFormatFileList { get; } = new List() - { - new UploadFile { FileName = "Test.xls" }, - new UploadFile { FileName = "Test.doc" }, - new UploadFile { FileName = "Test.ppt" }, - new UploadFile { FileName = "Test.mp3" }, - new UploadFile { FileName = "Test.mp4" }, - new UploadFile { FileName = "Test.pdf" }, - new UploadFile { FileName = "Test.cs" }, - new UploadFile { FileName = "Test.zip" }, - new UploadFile { FileName = "Test.txt" }, - new UploadFile { FileName = "Test.dat" } - }; - - private CancellationTokenSource? ReadToken { get; set; } - - private static long MaxFileLength => 200 * 1024 * 1024; - - private async Task OnCardUpload(UploadFile file) - { - if (file != null && file.File != null) - { - // 服务器端验证当文件大于 2MB 时提示文件太大信息 - if (file.Size > MaxFileLength) - { - await ToastService.Information(Localizer["UploadsFileMsg"], Localizer["UploadsFileError"]); - file.Code = 1; - file.Error = Localizer["UploadsFileError"]; - } - else - { - await SaveToFile(file); - } - } - } - - private async Task SaveToFile(UploadFile file) - { - // Server Side 使用 - // Web Assembly 模式下必须使用 webapi 方式去保存文件到服务器或者数据库中 - // 生成写入文件名称 - var ret = false; - if (!string.IsNullOrEmpty(SiteOptions.CurrentValue.WebRootPath)) - { - var uploaderFolder = Path.Combine(SiteOptions.CurrentValue.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader"); - file.FileName = $"{Path.GetFileNameWithoutExtension(file.OriginFileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(file.OriginFileName)}"; - var fileName = Path.Combine(uploaderFolder, file.FileName); - - ReadToken ??= new CancellationTokenSource(); - ret = await file.SaveToFileAsync(fileName, MaxFileLength, ReadToken.Token); - - if (ret) - { - // 保存成功 - file.PrevUrl = $"images/uploader/{file.FileName}"; - } - else - { - var errorMessage = $"{Localizer["UploadsSaveFileError"]} {file.OriginFileName}"; - file.Code = 1; - file.Error = errorMessage; - await ToastService.Error(Localizer["UploadFile"], errorMessage); - } - } - else - { - file.Code = 1; - file.Error = Localizer["UploadsWasmError"]; - await ToastService.Information(Localizer["UploadsSaveFile"], Localizer["UploadsSaveFileMsg"]); - } - return ret; - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFolder.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFolder.razor deleted file mode 100644 index c81b42616ad8a07e40946be6316bf8f807b0cf11..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFolder.razor +++ /dev/null @@ -1,68 +0,0 @@ -@inject IStringLocalizer Localizer -@inject ToastService ToastService -@inject IOptionsMonitor SiteOptions -@implements IDisposable - -
-
- -
-
- -@code { - /// - /// Dispose - /// - public void Dispose() - { - ReadToken?.Cancel(); - GC.SuppressFinalize(this); - } - - private async Task OnUploadFolder(UploadFile file) - { - // 上传文件夹时会多次回调此方法 - await SaveToFile(file); - } - - private CancellationTokenSource? ReadToken { get; set; } - - private static long MaxFileLength => 200 * 1024 * 1024; - - private async Task SaveToFile(UploadFile file) - { - // Server Side 使用 - // Web Assembly 模式下必须使用 webapi 方式去保存文件到服务器或者数据库中 - // 生成写入文件名称 - var ret = false; - if (!string.IsNullOrEmpty(SiteOptions.CurrentValue.WebRootPath)) - { - var uploaderFolder = Path.Combine(SiteOptions.CurrentValue.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader"); - file.FileName = $"{Path.GetFileNameWithoutExtension(file.OriginFileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(file.OriginFileName)}"; - var fileName = Path.Combine(uploaderFolder, file.FileName); - - ReadToken ??= new CancellationTokenSource(); - ret = await file.SaveToFileAsync(fileName, MaxFileLength, ReadToken.Token); - - if (ret) - { - // 保存成功 - file.PrevUrl = $"images/uploader/{file.FileName}"; - } - else - { - var errorMessage = $"{Localizer["UploadsSaveFileError"]} {file.OriginFileName}"; - file.Code = 1; - file.Error = errorMessage; - await ToastService.Error(Localizer["UploadFile"], errorMessage); - } - } - else - { - file.Code = 1; - file.Error = Localizer["UploadsWasmError"]; - await ToastService.Information(Localizer["UploadsSaveFile"], Localizer["UploadsSaveFileMsg"]); - } - return ret; - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFormSettings.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFormSettings.razor deleted file mode 100644 index bdb94a8e45cae9fe2ac42207c48de9020b6e4dff..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadFormSettings.razor +++ /dev/null @@ -1,37 +0,0 @@ -@inject IStringLocalizer Localizer - - -
-
- -
-
- -
-
- -
-
-
- -@code { - private static Task OnSubmit(EditContext context) - { - // 示例代码请根据业务情况自行更改 - // var fileName = Foo.Picture?.Name; - return Task.CompletedTask; - } - - private Person Foo { get; set; } = new Person(); - - private class Person - { - [Required] - [StringLength(20, MinimumLength = 2)] - public string Name { get; set; } = "Blazor"; - - [Required] - [FileValidation(Extensions = new string[] { ".png", ".jpg", ".jpeg" }, FileSize = 50 * 1024)] - public IBrowserFile? Picture { get; set; } - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadIconTemplate.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadIconTemplate.razor deleted file mode 100644 index 942a2417d956a0215cd3264d9a5cd21e662202bb..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadIconTemplate.razor +++ /dev/null @@ -1,98 +0,0 @@ -@inject IStringLocalizer Localizer -@inject ToastService ToastService -@inject IOptionsMonitor SiteOptions -@implements IDisposable - - - - - - - - - - - -@code { - /// - /// Dispose - /// - public void Dispose() - { - ReadToken?.Cancel(); - GC.SuppressFinalize(this); - } - - private List DefaultFormatFileList { get; } = new List() - { - new UploadFile { FileName = "Test.xls" }, - new UploadFile { FileName = "Test.doc" }, - new UploadFile { FileName = "Test.ppt" }, - new UploadFile { FileName = "Test.mp3" }, - new UploadFile { FileName = "Test.mp4" }, - new UploadFile { FileName = "Test.pdf" }, - new UploadFile { FileName = "Test.cs" }, - new UploadFile { FileName = "Test.zip" }, - new UploadFile { FileName = "Test.txt" }, - new UploadFile { FileName = "Test.dat" } - }; - - private CancellationTokenSource? ReadToken { get; set; } - - private static long MaxFileLength => 200 * 1024 * 1024; - - private async Task OnCardUpload(UploadFile file) - { - if (file != null && file.File != null) - { - // 服务器端验证当文件大于 2MB 时提示文件太大信息 - if (file.Size > MaxFileLength) - { - await ToastService.Information(Localizer["UploadsFileMsg"], Localizer["UploadsFileError"]); - file.Code = 1; - file.Error = Localizer["UploadsFileError"]; - } - else - { - await SaveToFile(file); - } - } - } - - private async Task SaveToFile(UploadFile file) - { - // Server Side 使用 - // Web Assembly 模式下必须使用 webapi 方式去保存文件到服务器或者数据库中 - // 生成写入文件名称 - var ret = false; - if (!string.IsNullOrEmpty(SiteOptions.CurrentValue.WebRootPath)) - { - var uploaderFolder = Path.Combine(SiteOptions.CurrentValue.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader"); - file.FileName = $"{Path.GetFileNameWithoutExtension(file.OriginFileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(file.OriginFileName)}"; - var fileName = Path.Combine(uploaderFolder, file.FileName); - - ReadToken ??= new CancellationTokenSource(); - ret = await file.SaveToFileAsync(fileName, MaxFileLength, ReadToken.Token); - - if (ret) - { - // 保存成功 - file.PrevUrl = $"images/uploader/{file.FileName}"; - } - else - { - var errorMessage = $"{Localizer["UploadsSaveFileError"]} {file.OriginFileName}"; - file.Code = 1; - file.Error = errorMessage; - await ToastService.Error(Localizer["UploadFile"], errorMessage); - } - } - else - { - file.Code = 1; - file.Error = Localizer["UploadsWasmError"]; - await ToastService.Information(Localizer["UploadsSaveFile"], Localizer["UploadsSaveFileMsg"]); - } - return ret; - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadNormal.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadNormal.razor deleted file mode 100644 index 86dc7b9280ab0807272800b256d64e235bdf533b..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadNormal.razor +++ /dev/null @@ -1,36 +0,0 @@ -@inject IStringLocalizer Localizer - -
-
- - -
-
- - -
-
- - -
-
- - -@code { - [NotNull] - private ConsoleLogger? Logger { get; set; } - - private Task OnFileChange(UploadFile file) - { - // 未真正保存文件 - // file.SaveToFile() - Logger.Log($"{file.File!.Name} {Localizer["UploadsSuccess"]}"); - return Task.FromResult(""); - } - - private Task OnFileDelete(UploadFile item) - { - Logger.Log($"{item.OriginFileName} {Localizer["UploadsRemoveMsg"]}"); - return Task.FromResult(true); - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadPreCardStyle.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadPreCardStyle.razor deleted file mode 100644 index dfbcd97c59cbc743c1f80336f755bb9565d4c397..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadPreCardStyle.razor +++ /dev/null @@ -1,85 +0,0 @@ -@inject IStringLocalizer Localizer -@inject ToastService ToastService -@inject IOptionsMonitor SiteOptions -@implements IDisposable - -
-
-

@((MarkupString)Localizer["UploadPreCardStyleTips1"].Value)

- -
-
-

@((MarkupString)Localizer["UploadPreCardStyleTips2"].Value)

- -
-
- -@code { - /// - /// Dispose - /// - public void Dispose() - { - ReadToken?.Cancel(); - GC.SuppressFinalize(this); - } - - private CancellationTokenSource? ReadToken { get; set; } - - private static long MaxFileLength => 200 * 1024 * 1024; - - private async Task OnCardUpload(UploadFile file) - { - if (file != null && file.File != null) - { - // 服务器端验证当文件大于 2MB 时提示文件太大信息 - if (file.Size > MaxFileLength) - { - await ToastService.Information(Localizer["UploadsFileMsg"], Localizer["UploadsFileError"]); - file.Code = 1; - file.Error = Localizer["UploadsFileError"]; - } - else - { - await SaveToFile(file); - } - } - } - - private async Task SaveToFile(UploadFile file) - { - // Server Side 使用 - // Web Assembly 模式下必须使用 webapi 方式去保存文件到服务器或者数据库中 - // 生成写入文件名称 - var ret = false; - if (!string.IsNullOrEmpty(SiteOptions.CurrentValue.WebRootPath)) - { - var uploaderFolder = Path.Combine(SiteOptions.CurrentValue.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader"); - file.FileName = $"{Path.GetFileNameWithoutExtension(file.OriginFileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(file.OriginFileName)}"; - var fileName = Path.Combine(uploaderFolder, file.FileName); - - ReadToken ??= new CancellationTokenSource(); - ret = await file.SaveToFileAsync(fileName, MaxFileLength, ReadToken.Token); - - if (ret) - { - // 保存成功 - file.PrevUrl = $"images/uploader/{file.FileName}"; - } - else - { - var errorMessage = $"{Localizer["UploadsSaveFileError"]} {file.OriginFileName}"; - file.Code = 1; - file.Error = errorMessage; - await ToastService.Error(Localizer["UploadFile"], errorMessage); - } - } - else - { - file.Code = 1; - file.Error = Localizer["UploadsWasmError"]; - await ToastService.Information(Localizer["UploadsSaveFile"], Localizer["UploadsSaveFileMsg"]); - } - return ret; - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadedFiles.razor b/src/BootstrapBlazor.Shared/Demos/Uploads/UploadedFiles.razor deleted file mode 100644 index 9f8d68afa76ae48ed375eae0160e264b96c941df..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/Uploads/UploadedFiles.razor +++ /dev/null @@ -1,37 +0,0 @@ -@inject ToastService ToastService -@implements IDisposable - -
-
- -
-
- -@code { - /// - /// Dispose - /// - public void Dispose() - { - GC.SuppressFinalize(this); - } - - private async Task OnDownload(UploadFile item) - { - await ToastService.Success("文件下载", $"下载 {item.FileName} 成功"); - } - - private List DefaultFormatFileList { get; } = new List() - { - new UploadFile { FileName = "Test.xls" }, - new UploadFile { FileName = "Test.doc" }, - new UploadFile { FileName = "Test.ppt" }, - new UploadFile { FileName = "Test.mp3" }, - new UploadFile { FileName = "Test.mp4" }, - new UploadFile { FileName = "Test.pdf" }, - new UploadFile { FileName = "Test.cs" }, - new UploadFile { FileName = "Test.zip" }, - new UploadFile { FileName = "Test.txt" }, - new UploadFile { FileName = "Test.dat" } - }; -} diff --git a/src/BootstrapBlazor.Shared/Demos/VideoPlayers/VideoPlayersChangeURL.razor b/src/BootstrapBlazor.Shared/Demos/VideoPlayers/VideoPlayersChangeURL.razor deleted file mode 100644 index cf2893481d6d7286e5a3e310fc88304f77f16fd0..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/VideoPlayers/VideoPlayersChangeURL.razor +++ /dev/null @@ -1,66 +0,0 @@ -
-
- -
-
- -
-
- -
-
- -
-
-
- - -@code { - private string MineType = "video/mp4"; - private string Url = "//vjs.zencdn.net/v/oceans.mp4"; - - [NotNull] - private VideoPlayer? Player { get; set; } - - private List VideoList { get; } = new() - { - "https://rtvelivestream.akamaized.net/rtvesec/la1/la1_main.m3u8", - "https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8", - "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8", - "https://res.cloudinary.com/dannykeane/video/upload/sp_full_hd/q_80:qmax_90,ac_none/v1/dk-memoji-dark.m3u8", - "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8", - "https://moctobpltc-i.akamaihd.net/hls/live/571329/eight/playlist.m3u8", - "https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8", - "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.mp4/.m3u8", - "https://diceyk6a7voy4.cloudfront.net/e78752a1-2e83-43fa-85ae-3d508be29366/hls/fitfest-sample-1_Ott_Hls_Ts_Avc_Aac_16x9_1280x720p_30Hz_6.0Mbps_qvbr.m3u8" - }; - - private List Items { get; } = new(); - - /// - /// OnInitialized 方法 - /// - protected override void OnInitialized() - { - base.OnInitialized(); - for (var i = 0; i < VideoList.Count; i++) - { - Items.Add(new SelectedItem { Text = $"TestVideo{i}", Value = VideoList[i] }); - } - Items.Add(new SelectedItem { Text = "Mp4", Value = "//vjs.zencdn.net/v/oceans.mp4" }); - } - - private async Task ChangeURL(SelectedItem e) - { - Url = e.Value; - MineType = e.Value.EndsWith("mp4") ? "video/mp4" : "application/x-mpegURL"; - StateHasChanged(); - await Apply(); - } - - private async Task Apply() - { - await Player.SetPoster("//vjs.zencdn.net/v/oceans.png"); - await Player.Reload(Url, MineType); - } -} diff --git a/src/BootstrapBlazor.Shared/Demos/VideoPlayers/VideoPlayersNomal.razor b/src/BootstrapBlazor.Shared/Demos/VideoPlayers/VideoPlayersNomal.razor deleted file mode 100644 index 63045e929580b2127fe7467f1f67e01ddd57ed0b..0000000000000000000000000000000000000000 --- a/src/BootstrapBlazor.Shared/Demos/VideoPlayers/VideoPlayersNomal.razor +++ /dev/null @@ -1,8 +0,0 @@ -
-
- -
-
- -
-
diff --git a/src/BootstrapBlazor.Shared/Locales/en.json b/src/BootstrapBlazor.Shared/Locales/en.json index 7bc4b118de2df2557b852b7506fecf3ba8cfb699..6eba80353e2d56d3c47f32526801c1928fe7feea 100644 --- a/src/BootstrapBlazor.Shared/Locales/en.json +++ b/src/BootstrapBlazor.Shared/Locales/en.json @@ -5876,12 +5876,24 @@ "PdfReaderCompatibilityModeTips": "- Chrome < 97 automatically uses version 2.4.456
- Chrome < 109 automatically uses version 2.6.347
- Note: ReadOnly and Watermark cannot be used in these two compatibility modes" }, "BootstrapBlazor.Shared.Samples.VideoPlayers": { - "Title": "VideoPlayer", - "BaseUsageText": "Basic usage", - "BaseUsageIntro": "", - "BaseUsageText2": "Switch playback resources", - "BaseUsageIntro2": "Use the Reload method to switch playback resources", - "Tips": "Silent mode enabled by default, this is the way for autoplay follow the modern browser standards." + "VideoPlayersTitle": "VideoPlayer", + "VideoPlayersNomalTitle": "Basic usage", + "VideoPlayersNomalIntro": "", + "VideoPlayersChangeURLTitle": "Switch playback resources", + "VideoPlayersChangeURLIntro": "Use the Reload method to switch playback resources", + "VideoPlayersTips": "Silent mode enabled by default, this is the way for autoplay follow the modern browser standards.", + "MineType": "MineType", + "ResourceUrl": "Resource Address", + "MineTypeDesc": "Resource types", + "ValueList": "(see footer)", + "Width": "Width", + "Height": "Height", + "ShowControls": "Displays the control bar", + "AutoPaly": "Autoplay", + "Poster": "Set the cover resource, relative or absolute path", + "SwitchResource": "Toggle playback resources", + "SetPoster": "Set the cover", + "OnError": "Error callback" }, "BootstrapBlazor.Shared.Components.PackageTips": { "Tips": "
Precautions
This component relies on {0}, which needs to reference its component package when using this component
Nuget Install
Use nuget.org to install {0} component
" diff --git a/src/BootstrapBlazor.Shared/Locales/zh.json b/src/BootstrapBlazor.Shared/Locales/zh.json index d0f92e2a83afc2a55fd22957b439cb37e302e36b..ada3b161253a98fd6710881397afb9d91221ade0 100644 --- a/src/BootstrapBlazor.Shared/Locales/zh.json +++ b/src/BootstrapBlazor.Shared/Locales/zh.json @@ -5897,12 +5897,24 @@ "PdfReaderCompatibilityModeTips": "- Chrome < 97 自动使用 2.4.456 版本
- Chrome < 109 自动使用 2.6.347 版本
- 注:ReadOnly 和 Watermark 在这两种兼容模式下不能使用" }, "BootstrapBlazor.Shared.Samples.VideoPlayers": { - "Title": "VideoPlayer 视频播放器", - "BaseUsageText": "基础用法", - "BaseUsageIntro": "", - "BaseUsageText2": "切换播放资源", - "BaseUsageIntro2": "使用 Reload 方法切换播放资源", - "Tips": "默认启用静音模式,只有这样自动播放功能才符合现代浏览器标准." + "VideoPlayersTitle": "VideoPlayer 视频播放器", + "VideoPlayersNomalTitle": "基础用法", + "VideoPlayersNomalIntro": "", + "VideoPlayersChangeURLTitle": "切换播放资源", + "VideoPlayersChangeURLIntro": "使用 Reload 方法切换播放资源", + "VideoPlayersTips": "默认启用静音模式,只有这样自动播放功能才符合现代浏览器标准.", + "MineType": "MineType 类型", + "ResourceUrl": "资源地址", + "MineTypeDesc": "资源类型,video/mp4, application/x-mpegURL, video/ogg .. ", + "ValueList": "(见页脚)", + "Width": "宽度", + "Height": "高度", + "ShowControls": "显示控制条", + "AutoPaly": "自动播放", + "Poster": "设置封面资源,相对或者绝对路径", + "SwitchResource": "切换播放资源", + "SetPoster": "设置封面", + "OnError": "错误回调" }, "BootstrapBlazor.Shared.Components.PackageTips": { "Tips": "
注意事项 :
本组件依赖于 {0},使用本组件时需要引用其组件包
Nuget 包安装
使用 nuget.org 进行 {0} 组件的安装
" diff --git a/src/BootstrapBlazor.Shared/Samples/Uploads.razor b/src/BootstrapBlazor.Shared/Samples/Uploads.razor index 9d9ab65c37e317e4d9ba5fb226dd7c2f5d882396..df376f45d108dcb5dda1bf40339ab8e387913970 100644 --- a/src/BootstrapBlazor.Shared/Samples/Uploads.razor +++ b/src/BootstrapBlazor.Shared/Samples/Uploads.razor @@ -1,6 +1,8 @@ @page "/uploads" @inject IOptionsMonitor SiteOptions @inject IStringLocalizer Localizer +@inject ToastService ToastService +@implements IDisposable

@Localizer["UploadsTitle"]

@@ -12,48 +14,128 @@ + Name="Normal"> +
+
+ + +
+
+ + +
+
+ + +
+
+
+ Name="FormSettings">
  • @((MarkupString)Localizer["UploadFormSettingsLi1"].Value)
  • @((MarkupString)Localizer["UploadFormSettingsLi2"].Value)
+ +
+
+ +
+
+ +
+
+ +
+
+
+ Name="ClickUpload"> +
+
+

@((MarkupString)Localizer["UploadClickUploadTips1"].Value)

+ +
+
+

@((MarkupString)Localizer["UploadClickUploadTips2"].Value)

+ +

@((MarkupString)Localizer["UploadClickUploadTips3ShowUploadList"].Value)

+
+ Name="UploadedFiles"> +
+
+ +
+
+ Name="UploadFolder"> +
+
+ +
+
+ Name="AvatarUpload"> +
+
+

@Localizer["AvatarUploadTips1"]

+ +
+
+

@Localizer["AvatarUploadTips2"]

+ +
+
+

@((MarkupString)Localizer["AvatarUploadTips3"].Value)

+ +

@((MarkupString)Localizer["AvatarUploadTips5"].Value)

+

+ +
+
+

@((MarkupString)Localizer["AvatarUploadTips6"].Value)

+ +
+
+

@((MarkupString)Localizer["AvatarUploadTips7"].Value)

+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ Name="PreCardStyle">

@((MarkupString)Localizer["UploadPreCardStyleSSR"].Value)
@((MarkupString)Localizer["UploadPreCardStyleServerSide"].Value)
@@ -62,24 +144,42 @@
@((MarkupString)Localizer["UploadPreCardStyleLink", SiteOptions.CurrentValue.VideoLibUrl].Value)
@((MarkupString)Localizer["UploadPreCardStyleValidation"].Value)

+
+
+

@((MarkupString)Localizer["UploadPreCardStyleTips1"].Value)

+ +
+
+

@((MarkupString)Localizer["UploadPreCardStyleTips2"].Value)

+ +
+
+ Name="FileIcon"> + + Name="IconTemplate"> + + + + + + + + + + Name="Base64"> + diff --git a/src/BootstrapBlazor.Shared/Samples/Uploads.razor.cs b/src/BootstrapBlazor.Shared/Samples/Uploads.razor.cs index f4fe049be1abea0c25124a8baf4308506ac6a4ff..b1a54928b9c9b2d51de2a3cdd40fab2eff872523 100644 --- a/src/BootstrapBlazor.Shared/Samples/Uploads.razor.cs +++ b/src/BootstrapBlazor.Shared/Samples/Uploads.razor.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Website: https://www.blazor.zone or https://argozhang.github.io/ +using Microsoft.AspNetCore.Components.Forms; + namespace BootstrapBlazor.Shared.Samples; /// @@ -9,6 +11,198 @@ namespace BootstrapBlazor.Shared.Samples; /// public sealed partial class Uploads { + [NotNull] + private ConsoleLogger? Logger { get; set; } + + private static readonly Random random = new(); + + private CancellationTokenSource? ReadToken { get; set; } + + private static long MaxFileLength => 200 * 1024 * 1024; + + private Person Foo { get; set; } = new Person(); + + private List PreviewFileList { get; } = new(new[] { new UploadFile { PrevUrl = "./images/Argo.png" } }); + + private CancellationTokenSource? ReadAvatarToken { get; set; } + + private List DefaultFormatFileList { get; } = new List() +{ + new UploadFile { FileName = "Test.xls" }, + new UploadFile { FileName = "Test.doc" }, + new UploadFile { FileName = "Test.ppt" }, + new UploadFile { FileName = "Test.mp3" }, + new UploadFile { FileName = "Test.mp4" }, + new UploadFile { FileName = "Test.pdf" }, + new UploadFile { FileName = "Test.cs" }, + new UploadFile { FileName = "Test.zip" }, + new UploadFile { FileName = "Test.txt" }, + new UploadFile { FileName = "Test.dat" } + }; + + private List Base64FormatFileList { get; } = new List() + { + new UploadFile { FileName = "Test", PrevUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAkCAYAAAD/yagrAAAE60lEQVR4AWJwL/AB9GIWvI0jURz/L1NomZmZP8p9kWNmhnIbKPdomZmZGcJgO7QsWMbce55Yl11t47FbVdKTYpjOr/+H4y4Z/MpYeJVV8KVvokFRylq9osKfVtGQ/NHyPl2CbNVGwau2oOlmgUDJtDJGzxtvvIA3vRH+7IgeA0VtYhQBtKPlToFgC6RY58aggfwLNKhr0Zry2NnPrpIM2YGW2+UBG1IEmdGVJEVXE+hQXt8joKhLjdGVZHd7TSD9DHmT3J1dheroSF4fhnvUVQwbZx9UOnHSzQjkTN0tIG+8hFdbxet4PQOG4WqJwN1hFVb+xUBmCblxvxRkIE+Q+Yf0T31NSrp4/RV4FhHgoSTchQRZBK4D1+Fe2q2g8CYXU6buQyNDaiZKZhn0IYXHVwbkRQydHyawOAGGisa/o3DvI/jF3QKKiuAy+LKs5CvaXMLdeXb35wbkKTjmReDZHysCBosWJqN7r0jZ/VfgXtIlUNQnVpK7D4nNJSC5BHGi1d108Ppr8MxlF0cJqBSyFJaUfUnvHLyO4cttgaI+NhGB7HE0MaSUks/gU5vwe1gv5tfhmUmAhxME8jbIUtiEDus+fhmDJlgCRY0ylZRZhybKWtNinmYlH9NvL5puO3m9UHOkgzb3xuF5HCkDyhYiSwrYVfQPTpYChTc+E35tG9VJBjGFFNmtVlNMDnjzbx0EBpKq1eTeh2awbArBRuHadBWu6WVB4U/NITfuobYoCZl7QL//wDtr+nTmsgzQh2Kwgtz7QAZWFeGw/RI8s94Kigp1PvzZg2i9x11FDtKn/oZCoZdZxhaAXmG4/ohJKHudLE1Gyu66DOfs10BRR5CU3TKQIrtzj9BAkF991dsMslTZEClLsI+jFmANZYFAdAJl9QG03jWH9GrcFh9QTP4Of6GfJGSpsv1J2aoEKRuWCANNJNqOFAaPAW36rVRMCjVf6ZCtqYF2p6Asxg5mWK6tQamY9RCs8z1wF+FxTR5UqYT/3GC7oCkMHcjxKguq6cnl+Egf2whip3C9Yu56jk+GXXOtv1XIa8L1f3AFkHe9az83AmNanwV/bhfa5JKJ3n1slCUL8dk7CNfvVFMfySRThoxbK7fh18tTZXI2QeySLk88IRGsbHkqQj6wUJ72G5CloCXKZrdbLPgVMgVfQMq5m97bfQWOOeVbaK02nSA2ofn2y662UJE47horLZTe38oDjdxQUhmawocxa0OJ5hXjnZE4w1y0uc/iULKGfk+xNuZxI/BnjhFs+THPq4phmTsbeYPXRjFsJJ+NSMlnInHkxrwzGDjR3uBcG1/B/b/TwZkhubb6tP2oVfTAD2G4kw9vYiA2h+zy4GwYxd7S4qGOgd6oqVn6re1DTXiO4e4wPF+yQlF4ZCBfheSPIjJn+ciS/w93qjA6aZYqeQ5D3dTqvuE6GZNTkov5vqsYvLh7j8u1sWWkLIdBQR+q+XdtaKGhJCWBDpkwgSw9gRpKyoNKw6rjCLCDP4yVflSgWFwt3C0HSUo2BTFYX28fVAaWPpDx7wtwjOSSUszawnUT0KTudlfrFQwZ3WNf867CNZQhk/C8kIFUhJLt/O3Jzn62IYNwrUvA8zws4W61CGlDSfugXMz5pJgiSFYyXMYiRXdH4GmyqaR9UHLxzxG41KAwpZxRPN4kRf85Z5I4MvYfFUFGfemJG40AAAAASUVORK5CYII=" }, + }; + + private Task OnFileChange(UploadFile file) + { + // 未真正保存文件 + // file.SaveToFile() + Logger.Log($"{file.File!.Name} {Localizer["UploadsSuccess"]}"); + return Task.FromResult(""); + } + + private Task OnFileDelete(UploadFile item) + { + Logger.Log($"{item.OriginFileName} {Localizer["UploadsRemoveMsg"]}"); + return Task.FromResult(true); + } + + private static Task OnSubmit(EditContext context) + { + // 示例代码请根据业务情况自行更改 + // var fileName = Foo.Picture?.Name; + return Task.CompletedTask; + } + + private async Task OnClickToUpload(UploadFile file) + { + // 示例代码,模拟 80% 几率保存成功 + var error = random.Next(1, 100) > 80; + if (error) + { + file.Code = 1; + file.Error = Localizer["UploadsError"]; + } + else + { + await SaveToFile(file); + } + } + + private async Task OnClickToUploadNoUploadList(UploadFile file) + { + await ToastService.Success("Upload", $"{file.OriginFileName} uploaded success."); + } + + private async Task SaveToFile(UploadFile file) + { + // Server Side 使用 + // Web Assembly 模式下必须使用 webapi 方式去保存文件到服务器或者数据库中 + // 生成写入文件名称 + var ret = false; + if (!string.IsNullOrEmpty(SiteOptions.CurrentValue.WebRootPath)) + { + var uploaderFolder = Path.Combine(SiteOptions.CurrentValue.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader"); + file.FileName = $"{Path.GetFileNameWithoutExtension(file.OriginFileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(file.OriginFileName)}"; + var fileName = Path.Combine(uploaderFolder, file.FileName); + + ReadToken ??= new CancellationTokenSource(); + ret = await file.SaveToFileAsync(fileName, MaxFileLength, ReadToken.Token); + + if (ret) + { + // 保存成功 + file.PrevUrl = $"images/uploader/{file.FileName}"; + } + else + { + var errorMessage = $"{Localizer["UploadsSaveFileError"]} {file.OriginFileName}"; + file.Code = 1; + file.Error = errorMessage; + await ToastService.Error(Localizer["UploadFile"], errorMessage); + } + } + else + { + file.Code = 1; + file.Error = Localizer["UploadsWasmError"]; + await ToastService.Information(Localizer["UploadsSaveFile"], Localizer["UploadsSaveFileMsg"]); + } + return ret; + } + + private async Task OnDownload(UploadFile item) + { + await ToastService.Success("文件下载", $"下载 {item.FileName} 成功"); + } + + private async Task OnUploadFolder(UploadFile file) + { + // 上传文件夹时会多次回调此方法 + await SaveToFile(file); + } + + private async Task OnAvatarUpload(UploadFile file) + { + // 示例代码,使用 base64 格式 + if (file != null && file.File != null) + { + var format = file.File.ContentType; + if (CheckValidAvatarFormat(format)) + { + ReadAvatarToken ??= new CancellationTokenSource(); + if (ReadAvatarToken.IsCancellationRequested) + { + ReadAvatarToken.Dispose(); + ReadAvatarToken = new CancellationTokenSource(); + } + + await file.RequestBase64ImageFileAsync(format, 640, 480, MaxFileLength, ReadAvatarToken.Token); + } + else + { + file.Code = 1; + file.Error = Localizer["UploadsFormatError"]; + } + + if (file.Code != 0) + { + await ToastService.Error(Localizer["UploadsAvatarMsg"], $"{file.Error} {format}"); + } + } + } + + private static bool CheckValidAvatarFormat(string format) + { + return "jpg;png;bmp;gif;jpeg".Split(';').Any(f => format.Contains(f, StringComparison.OrdinalIgnoreCase)); + } + + private Task OnAvatarValidSubmit(EditContext context) + { + Logger.Log(Foo.Picture?.Name ?? ""); + return Task.CompletedTask; + } + + private async Task OnCardUpload(UploadFile file) + { + if (file != null && file.File != null) + { + // 服务器端验证当文件大于 2MB 时提示文件太大信息 + if (file.Size > MaxFileLength) + { + await ToastService.Information(Localizer["UploadsFileMsg"], Localizer["UploadsFileError"]); + file.Code = 1; + file.Error = Localizer["UploadsFileError"]; + } + else + { + await SaveToFile(file); + } + } + } + + /// + /// Dispose + /// + public void Dispose() + { + ReadToken?.Cancel(); + ReadAvatarToken?.Cancel(); + GC.SuppressFinalize(this); + } + private IEnumerable GetInputAttributes() => new AttributeItem[] { new AttributeItem() { @@ -265,4 +459,15 @@ public sealed partial class Uploads DefaultValue = " — " } }; + + private class Person + { + [Required] + [StringLength(20, MinimumLength = 2)] + public string Name { get; set; } = "Blazor"; + + [Required] + [FileValidation(Extensions = new string[] { ".png", ".jpg", ".jpeg" }, FileSize = 50 * 1024)] + public IBrowserFile? Picture { get; set; } + } } diff --git a/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor b/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor index 33bf878630ec44d6f83653d38439f3fa89e22bd5..c29fa9d8f3fc14a9eefe4599fc345479e0ee0902 100644 --- a/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor +++ b/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor @@ -6,24 +6,46 @@ - +

@((MarkupString)Localizer["VideoPlayersTips"].Value)

+ Name="Nomal"> +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ Name="ChangeURL"> +
+
+ +
+
+ +
+

-
MineType 类型
+
@Localizer["MineType"]
  1. opus: 'video/ogg'
  2. ogv: 'video/ogg'
  3. diff --git a/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor.cs b/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor.cs index f1b3e0bcfeb9338f67de3bc6772c799bb0b6f805..5b02a46adf1613d4c7f6b4fa896d3dd377f5d986 100644 --- a/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor.cs +++ b/src/BootstrapBlazor.Shared/Samples/VideoPlayers.razor.cs @@ -9,6 +9,54 @@ namespace BootstrapBlazor.Shared.Samples; /// public partial class VideoPlayers { + private string MineType = "video/mp4"; + private string Url = "//vjs.zencdn.net/v/oceans.mp4"; + + [NotNull] + private VideoPlayer? Player { get; set; } + + private List VideoList { get; } = new() + { + "https://rtvelivestream.akamaized.net/rtvesec/la1/la1_main.m3u8", + "https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8", + "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8", + "https://res.cloudinary.com/dannykeane/video/upload/sp_full_hd/q_80:qmax_90,ac_none/v1/dk-memoji-dark.m3u8", + "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8", + "https://moctobpltc-i.akamaihd.net/hls/live/571329/eight/playlist.m3u8", + "https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8", + "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.mp4/.m3u8", + "https://diceyk6a7voy4.cloudfront.net/e78752a1-2e83-43fa-85ae-3d508be29366/hls/fitfest-sample-1_Ott_Hls_Ts_Avc_Aac_16x9_1280x720p_30Hz_6.0Mbps_qvbr.m3u8" + }; + + private List Items { get; } = new(); + + /// + /// OnInitialized 方法 + /// + protected override void OnInitialized() + { + base.OnInitialized(); + for (var i = 0; i < VideoList.Count; i++) + { + Items.Add(new SelectedItem { Text = $"TestVideo{i}", Value = VideoList[i] }); + } + Items.Add(new SelectedItem { Text = "Mp4", Value = "//vjs.zencdn.net/v/oceans.mp4" }); + } + + private async Task ChangeURL(SelectedItem e) + { + Url = e.Value; + MineType = e.Value.EndsWith("mp4") ? "video/mp4" : "application/x-mpegURL"; + StateHasChanged(); + await Apply(); + } + + private async Task Apply() + { + await Player.SetPoster("//vjs.zencdn.net/v/oceans.png"); + await Player.Reload(Url, MineType); + } + /// /// 获得属性方法 /// @@ -18,70 +66,70 @@ public partial class VideoPlayers // TODO: 移动到数据库中 new() { Name = nameof(VideoPlayer.Url), - Description = "资源地址", + Description = Localizer["ResourceUrl"], Type = "string", ValueList = " — ", DefaultValue = " — " }, new() { Name = nameof(VideoPlayer.MineType), - Description = "资源类型,video/mp4, application/x-mpegURL, video/ogg .. ", + Description = Localizer["MineTypeDesc"], Type = "string?", - ValueList = "(见页脚)", + ValueList = Localizer["ValueList"], DefaultValue = "application/x-mpegURL" }, new() { Name = nameof(VideoPlayer.Width), - Description = "宽度", + Description = Localizer["Width"], Type = "int", ValueList = " — ", DefaultValue = "300" }, new() { Name = nameof(VideoPlayer.Height), - Description = "高度", + Description = Localizer["Height"], Type = "int", ValueList = " — ", DefaultValue = "200" }, new() { Name = nameof(VideoPlayer.Controls), - Description = "显示控制条", + Description = Localizer["ShowBar"], Type = "bool", ValueList = "true|false", DefaultValue = "true" }, new() { Name = nameof(VideoPlayer.Autoplay), - Description = "自动播放", + Description = Localizer["AutoPaly"], Type = "bool", ValueList = "true|false", DefaultValue = "true" }, new() { Name = nameof(VideoPlayer.Poster), - Description = "设置封面资源,相对或者绝对路径", + Description = Localizer["Poster"], Type = "string?", ValueList = " — ", DefaultValue = " — " }, new() { Name = "Reload(string url, string type)", - Description = "切换播放资源", + Description = Localizer["SwitchResource"], Type = "async Task", ValueList = " — ", DefaultValue = " — " }, new() { Name = "SetPoster(string poster)", - Description = "设置封面", + Description = Localizer["SetPoster"], Type = "async Task", ValueList = " — ", DefaultValue = " — " }, new() { Name = "OnError", - Description = "错误回调", + Description = Localizer["OnError"], Type = "Func?", ValueList = " — ", DefaultValue = " — "