I have a Blazor Component Library. In the library my js code generates a huge string which is about 160 000 characters. Simplified JS below (actualy this is base64 string)
export function showPrompt(message): Uint8Array {
alert(message);
let str = "";
for(let i = 0; i < 164232; i++)
str += "A";
return new TextEncoder().encode(str);
}
My C# code is:
async void CallJS() {
string? str = null;
IJSStreamReference? jsStream = await Prompt("After you will press ok, long string will be generated");
if (jsStream != null) {
using Stream referenceStream = await jsStream.OpenReadStreamAsync();
byte[] byteArray = new byte[referenceStream.Length];
int byteArrayCount = await referenceStream.ReadAsync(byteArray);
str = System.Text.Encoding.Default.GetString(byteArray, 0, byteArrayCount);
}
length = str?.Length ?? 0;
}
When I use this component in Blazor Server App, C# gets only 32 thousands chars. As I understand this is due to Signal-R limitation. I've found this topic: Pass large JS blob to Blazor byte[] and tried the solution, but even with the code below, c# receives only 50 000 characters.
services.AddSignalR(o => {
o.EnableDetailedErrors = true;
o.MaximumReceiveMessageSize = long.MaxValue;
});
How to pass a huge string from JS to C# in Blazor?
I have managed to solve this problem only by chanking the message:
TS: //Type Script Code:
let str = "";
//generate large string
export function exportImageAndGetBase64Length(message): number {
alert(message);
for(let i = 0; i < 164232; i++)
str += "A";
return str.length;
}
//get part of the generated string
export function getChunk(startIndex, endIndex): string {
return str.substring(startIndex, endIndex);
}
//finish transition and clean up the string
export function ClearBuffer() {
str = "";
}
Razor
inject Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.HubOptions> Options
C#:
async void GetLongStringFromJS() {
int fileLength = await module.InvokeAsync<int>("exportImageAndGetBase64Length", "long string of 164232 will be generated and send to c#");
HubOptions a = Options.Value;
int maximumSingnalRMessageSize = (a.MaximumReceiveMessageSize == null || a.MaximumReceiveMessageSize > 32768) ? 32768 : (int)a.MaximumReceiveMessageSize;
int chunkLength = (int)maximumSingnalRMessageSize / sizeof(char);
StringBuilder sb = new StringBuilder();
for (int startIndex = 0, endIndex = chunkLength; startIndex <= fileLength; startIndex += chunkLength, endIndex += chunkLength) {
if (endIndex > fileLength + 1)
endIndex = fileLength + 1;
string chunk = await module.InvokeAsync<string>("getChunk", startIndex, endIndex);
sb.Append(chunk);
}
length = sb.Length; //do somthing with your string
await module.InvokeVoidAsync("ClearBuffer");
this.StateHasChanged();
}