简体   繁体   English

Blazor:如何将很长的字符串从JS传递给C#?

[英]Blazor: How to pass very long string from JS to C#?

I have a Blazor Component Library.我有一个 Blazor 组件库。 In the library my js code generates a huge string which is about 160 000 characters.在库中,我的 js 代码生成了一个巨大的字符串,大约有 160 000 个字符。 Simplified JS below (actualy this is base64 string)下面的简化 JS(实际上这是 base64 字符串)

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:我的 C# 代码是:

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.当我在 Blazor 服务器应用程序中使用此组件时,C# 仅获得 32,000 个字符。 As I understand this is due to Signal-R limitation.据我了解,这是由于 Signal-R 的限制。 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.我找到了这个主题: 将大型 JS blob 传递给 Blazor byte[]并尝试了解决方案,但即使使用下面的代码,c# 也只收到 50 000 个字符。

  services.AddSignalR(o => {
    o.EnableDetailedErrors = true;
    o.MaximumReceiveMessageSize = long.MaxValue;
  });

How to pass a huge string from JS to C# in Blazor?如何在Blazor中将一个巨大的字符串从JS传给C#?

We hit the same problem - I think the problem is, that SignalR is chunking the message when using IJSStreamReference if it is too big.我们遇到了同样的问题 - 我认为问题是,如果 SignalR 太大,则在使用IJSStreamReference时会将消息分块。 When you call await referenceStream.ReadAsync(byteArray);当您调用await referenceStream.ReadAsync(byteArray); there is a posibillity that the Message isn't completely transfered yet.有可能消息尚未完全传输。

Try copying the referenceStream to an MemoryStream and call.ToArray() on it.尝试将referenceStream复制到MemoryStream并在其上调用.ToArray()。

async void CallJS() {
    string? str = null;
    IJSStreamReference? jsStream = await Prompt("After you will press ok, long string will be generated");
    if (jsStream != null) {
        await using Stream referenceStream = await jsStream.OpenReadStreamAsync();
        using var memStream = new MemoryStream();
        await referenceStream.CopyToAsync(memStream);
        var byteArray = memStream.ToArray();
        str =  System.Text.Encoding.Default.GetString(byteArray);
    }
    length = str?.Length ?? 0;
}

Or maybe even better, use an StreamReader :或者甚至更好,使用StreamReader

async void CallJS() {
    string? str = null;
    IJSStreamReference? jsStream = await Prompt("After you will press ok, long string will be generated");
    if (jsStream != null) {
        await using Stream referenceStream = await jsStream.OpenReadStreamAsync();
        using var sr = new StreamReader(referenceStream);
        var str = await sr.ReadToEndAsync();
    }
    length = str?.Length ?? 0;
}

If it still doesn't work, take a look at the maxAllowedSize Parameter of the OpenReadStreamAsync Method如果还是不行,看看OpenReadStreamAsync方法的maxAllowedSize参数

I have managed to solve this problem only by chanking the message:我已经设法通过发送消息来解决这个问题:

TS: //Type Script Code: TS: //输入脚本代码:

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 Razor

inject Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.HubOptions> Options

C#: 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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM