public static async ValueTask <RemoteJSDataStream> CreateRemoteJSDataStreamAsync( RemoteJSRuntime runtime, IJSStreamReference jsStreamReference, long totalLength, long signalRMaximumIncomingBytes, TimeSpan jsInteropDefaultCallTimeout, CancellationToken cancellationToken = default) { // Enforce minimum 1 kb, maximum 50 kb, SignalR message size. // We budget 512 bytes overhead for the transfer, thus leaving at least 512 bytes for data // transfer per chunk with a 1 kb message size. // Additionally, to maintain interactivity, we put an upper limit of 50 kb on the message size. var chunkSize = signalRMaximumIncomingBytes > 1024 ? Math.Min(signalRMaximumIncomingBytes, 50 * 1024) - 512 : throw new ArgumentException($"SignalR MaximumIncomingBytes must be at least 1 kb."); var streamId = runtime.RemoteJSDataStreamNextInstanceId++; var remoteJSDataStream = new RemoteJSDataStream(runtime, streamId, totalLength, jsInteropDefaultCallTimeout, cancellationToken); await runtime.InvokeVoidAsync("Blazor._internal.sendJSDataStream", jsStreamReference, streamId, chunkSize); return(remoteJSDataStream); }
// ReceiveJSDataChunk is used in a fire-and-forget context, so it's responsible for its own // error handling. internal async Task <bool> ReceiveJSDataChunk(long streamId, long chunkId, byte[] chunk, string error) { AssertInitialized(); AssertNotDisposed(); try { return(await Renderer.Dispatcher.InvokeAsync(() => { return RemoteJSDataStream.ReceiveData(JSRuntime, streamId, chunkId, chunk, error); })); } catch (Exception ex) { // An error completing JS interop means that the user sent invalid data, a well-behaved // client won't do this. Log.ReceiveJSDataChunkException(_logger, streamId, ex); await TryNotifyClientErrorAsync(Client, GetClientErrorMessage(ex, "Invalid chunk supplied to stream.")); UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); return(false); } }