I am trying to create an upload component that previews a video or image before actually uploading it.
<FluentInputFile
Id="video-upload"
Mode="InputFileMode.SaveToTemporaryFolder"
Accept="video/*"
MaximumFileSize="@(2000*1024*1024)"
@bind-ProgressPercent="@videoProgress"
OnCompleted="@OnVideoCompletedAsync"
Style="width:100%; height: 300px;">
<ChildContent>
<FluentIcon Value="@(new Icons.Regular.Size16.ArrowUpload())"></FluentIcon>
<span style="font-family: monospace; margin-left: 10px;">Video</span>
</ChildContent>
</FluentInputFile>
int videoProgress = 0;
List<FluentInputFileEventArgs> videos = default!;
FileInfo? video;
string? videoUrl;
private async Task OnVideoCompletedAsync(IEnumerable<FluentInputFileEventArgs> _videos) {
videos = _videos.ToList();
Console.WriteLine($"[EVENT] Video Dropped : {videos.Count()}");
videos.ForEach(x => Console.WriteLine($"Name: {x.Name}, Size: {x.Size/1000000f} mb"));
video = videos[0].LocalFile;
videoUrl = await embedFiles(video, "video/mp4");
videoProgress = 0;
StateHasChanged();
}
private async Task<string?> embedFiles(FileInfo? fileInfo, string format) {
if(fileInfo == null) {
return null;
}
byte[] bytes = new byte[fileInfo.Length];
using(FileStream fileStream = fileInfo.OpenRead()) {
await fileStream.ReadAsync(bytes);
}
string url = await JSRuntime.InvokeAsync<string>("bytesToDataURL", bytes, format);
Console.WriteLine($"[INFO] File URLs : {url}");
return url;
}
async function bytesToDataURL(bytes, format) {
const blob = new Blob([new Uint8Array(bytes)], format);
let url = URL.createObjectURL(blob);
console.log(url);
return url;
}
But if I understand this correctly this uploads the video to the server and then would have to send this back to the client as bytes for it to create the blob URL. This is fine for smaller files but I feel this back and forth way is wasteful when you have very large files. I could attach an event handler to FluentInputFile in JS directly but that would disrupt the actual event handlers.