How to send Javascript Blob to SingleR hub?

99 Views Asked by At

I added a javascript page that would allow the user to record voice using their microphone.

I want to send the recording to a SignalR hub

Here is the javascript code that does the recording and then when the sendButton is called, the byte array is send to the signalR hub using the upload function.

const connection = new signalR.HubConnectionBuilder().withUrl("/hub").build();

let audioRecorder;
let data = [];

navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {

        audioRecorder = new MediaRecorder(stream);

        audioRecorder.addEventListener('dataavailable', e => {
            data.push(e.data);
        });

        startButton.addEventListener('click', () => {
            audioRecorder.start();
        });

        stopButton.addEventListener('click', () => {
            audioRecorder.stop();
        });

        sendButton.addEventListener('click', async () => {

            const blobObj = new Blob(data, { type: 'audio/webm' });

            var bytes = await blobObj.arrayBuffer();

            const subject = new signalR.Subject();
            subject.next(bytes)
            connection.invoke('upload', 'filename', subject);
            subject.complete();
        });
    })

I added this code in the

public partial class MyHub : Hub<IMyHub>
{
    public async Task Upload(string filename, IAsyncEnumerable<byte> stream)
    {
        using var memoryStream = new MemoryStream();

        await foreach (var item in stream)
        {
            memoryStream.WriteByte(item);
        }
    }
}

The Upload method gets hit as expected, but the stream parameter has no data.

How can I upload the recording byte array to the SignalR hub?

1

There are 1 best solutions below

0
Jason Pan On

I agree with Brennan, but SignalR itself does not directly support sending byte arrays as individual parameters. You might consider converting the byte array to a Base64 string and then converting it back to a byte stream on the server side.

Here is the sample code for you.

sendButton.addEventListener('click', async () => {
    const blobObj = new Blob(data, { type: 'audio/webm' });

    var arrayBuffer = await blobObj.arrayBuffer();
    var bytes = new Uint8Array(arrayBuffer);
    var base64String = btoa(String.fromCharCode(...bytes));

    // Send Base64 string directly
    connection.invoke('Upload', 'filename', base64String);
});

Backend code

public async Task Upload(string filename, string base64Data)
{
    var bytes = Convert.FromBase64String(base64Data);

    //According to your needs
    //var filePath = Path.Combine("Your_Destination_folder_Path", filename);
    //await File.WriteAllBytesAsync(filePath, bytes);
}