admin管理员组

文章数量:1024354

I am trying to pass an array of byte from Blazor Client to a javascript function:

private async void ShowImage()
{
    SelectedImageBytes = await GetImageData();
    if (SelectedImageBytes.Any())
    {
        ReceivedDataLength = SelectedImageBytes.Length;
        //ReceivedDataLength is 131072, which is correct
        JS.InvokeVoidAsync("JS.setImage", SelectedImageBytes, 256, 256);
        
    }

    StateHasChanged();
}

On Javascript side:

function setImage(data, width, height)
{
    console.log("On Javascript I have received an array of " + data.length);
    //data.length is 174764
    console.log(data);

    //...
}

console.log(data) outputs the following:

Which seems to me a base64 string representation of my binary data. According wikipedia the size is incremented approximately by 33% going from byte array to base64 string representation, and this is true for this case: 131072 * 1.33 ~ 174764

My questions then are:

  • How to pass and receive a byte array from Blazor (C#) to Javascript without converting it to a string
  • If the previous is not possible, what is the best way to convert the base64 string to byte array on Javascript side.

I am trying to pass an array of byte from Blazor Client to a javascript function:

private async void ShowImage()
{
    SelectedImageBytes = await GetImageData();
    if (SelectedImageBytes.Any())
    {
        ReceivedDataLength = SelectedImageBytes.Length;
        //ReceivedDataLength is 131072, which is correct
        JS.InvokeVoidAsync("JS.setImage", SelectedImageBytes, 256, 256);
        
    }

    StateHasChanged();
}

On Javascript side:

function setImage(data, width, height)
{
    console.log("On Javascript I have received an array of " + data.length);
    //data.length is 174764
    console.log(data);

    //...
}

console.log(data) outputs the following:

Which seems to me a base64 string representation of my binary data. According wikipedia the size is incremented approximately by 33% going from byte array to base64 string representation, and this is true for this case: 131072 * 1.33 ~ 174764

My questions then are:

  • How to pass and receive a byte array from Blazor (C#) to Javascript without converting it to a string
  • If the previous is not possible, what is the best way to convert the base64 string to byte array on Javascript side.
Share Improve this question asked Nov 12, 2020 at 11:34 SturmSturm 4,12410 gold badges55 silver badges84 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

I gave it another go:

C#

public void CallJsUnMarshalled()
{
    var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;
    unmarshalledRuntime.InvokeUnmarshalled<byte[], int>("JsFunctions.MyFunctionUnmarshalled", MyBytes);
}

Javascript:

function MyFunctionUnmarshalled(bytes)
{
    const dataPtr = Blazor.platform.getArrayEntryPtr(bytes, 0, 4);
    const length = Blazor.platform.getArrayLength(bytes);
    var shorts = new Int16Array(Module.HEAPU8.buffer, dataPtr, length);
    return 0;
}

InvokeUnmarshalled requires a return it appears, therefore int in the template arguments. Instead of this probably a reference to the object has to be returned to dispose it. I would appreciate if someone can ment on this (will javascript free that memory when the byte array is not used anymore?).

First tests show an improvement of a factor of 50!

When you are using the interop service, the documentation says:

InvokeAsync takes an identifier for the JavaScript function that you wish to invoke along with any number of JSON-serializable arguments.

So what you observe is the serialization of your byte array into a base64 string, which is the out-of-the-box behavior. So, you are right. I haven't spotted a way to influence the serialization behavior of the JSInterop service.

The Blazer framework in .NET 5 offers you a way to skip the serialization overhead: IJSUnmarshalledRuntime.

But, in my experiments, it can't handle a byte array or any arrays at all.

To answer your second question, have a look at this discussion.

Convert base64 string to ArrayBuffer

I am trying to pass an array of byte from Blazor Client to a javascript function:

private async void ShowImage()
{
    SelectedImageBytes = await GetImageData();
    if (SelectedImageBytes.Any())
    {
        ReceivedDataLength = SelectedImageBytes.Length;
        //ReceivedDataLength is 131072, which is correct
        JS.InvokeVoidAsync("JS.setImage", SelectedImageBytes, 256, 256);
        
    }

    StateHasChanged();
}

On Javascript side:

function setImage(data, width, height)
{
    console.log("On Javascript I have received an array of " + data.length);
    //data.length is 174764
    console.log(data);

    //...
}

console.log(data) outputs the following:

Which seems to me a base64 string representation of my binary data. According wikipedia the size is incremented approximately by 33% going from byte array to base64 string representation, and this is true for this case: 131072 * 1.33 ~ 174764

My questions then are:

  • How to pass and receive a byte array from Blazor (C#) to Javascript without converting it to a string
  • If the previous is not possible, what is the best way to convert the base64 string to byte array on Javascript side.

I am trying to pass an array of byte from Blazor Client to a javascript function:

private async void ShowImage()
{
    SelectedImageBytes = await GetImageData();
    if (SelectedImageBytes.Any())
    {
        ReceivedDataLength = SelectedImageBytes.Length;
        //ReceivedDataLength is 131072, which is correct
        JS.InvokeVoidAsync("JS.setImage", SelectedImageBytes, 256, 256);
        
    }

    StateHasChanged();
}

On Javascript side:

function setImage(data, width, height)
{
    console.log("On Javascript I have received an array of " + data.length);
    //data.length is 174764
    console.log(data);

    //...
}

console.log(data) outputs the following:

Which seems to me a base64 string representation of my binary data. According wikipedia the size is incremented approximately by 33% going from byte array to base64 string representation, and this is true for this case: 131072 * 1.33 ~ 174764

My questions then are:

  • How to pass and receive a byte array from Blazor (C#) to Javascript without converting it to a string
  • If the previous is not possible, what is the best way to convert the base64 string to byte array on Javascript side.
Share Improve this question asked Nov 12, 2020 at 11:34 SturmSturm 4,12410 gold badges55 silver badges84 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

I gave it another go:

C#

public void CallJsUnMarshalled()
{
    var unmarshalledRuntime = (IJSUnmarshalledRuntime)JS;
    unmarshalledRuntime.InvokeUnmarshalled<byte[], int>("JsFunctions.MyFunctionUnmarshalled", MyBytes);
}

Javascript:

function MyFunctionUnmarshalled(bytes)
{
    const dataPtr = Blazor.platform.getArrayEntryPtr(bytes, 0, 4);
    const length = Blazor.platform.getArrayLength(bytes);
    var shorts = new Int16Array(Module.HEAPU8.buffer, dataPtr, length);
    return 0;
}

InvokeUnmarshalled requires a return it appears, therefore int in the template arguments. Instead of this probably a reference to the object has to be returned to dispose it. I would appreciate if someone can ment on this (will javascript free that memory when the byte array is not used anymore?).

First tests show an improvement of a factor of 50!

When you are using the interop service, the documentation says:

InvokeAsync takes an identifier for the JavaScript function that you wish to invoke along with any number of JSON-serializable arguments.

So what you observe is the serialization of your byte array into a base64 string, which is the out-of-the-box behavior. So, you are right. I haven't spotted a way to influence the serialization behavior of the JSInterop service.

The Blazer framework in .NET 5 offers you a way to skip the serialization overhead: IJSUnmarshalledRuntime.

But, in my experiments, it can't handle a byte array or any arrays at all.

To answer your second question, have a look at this discussion.

Convert base64 string to ArrayBuffer

本文标签: Blazor to Javascript byte array interopStack Overflow