将大型 JS blob 传递给 Blazor byte[]
Pass large JS blob to Blazor byte[]
我需要使用 Media API in JS, example 为 Blazor 录制一些音频,甚至可能是视频。然后,我想将记录的 Blob
内容从 JS 传递到 Blazor。只要是音频或视频内容,它就可以相当大。
到目前为止我尝试了什么
将数据编码为 ANSI 字符串或传递一个整数数组。这导致 InvalidDataException
、SignalR 断开连接、超时,大约一分钟后 SignalR 恢复正常并且 C# 收到 null
将数据编码为 base 64 或传递 UInt8Array
。结果是一样的。
直接从 JS 传递 Blob
、ArrayBuffer
或 FormData
。这导致 C# 中的空对象 ValueKind: {}
。
JS调用来源
recorder.stop();
recorder.exportWAV(async blob => {
const content = await (new Response(blob).arrayBuffer());
const contentNums = new Uint8Array(content);
const contentCodes = new TextDecoder('windows-1252').decode(contentNums);
const data = new FormData();
data.append('file', blob, 'Demo');
//success(window.URL.createObjectURL(blob));
console.log(blob)
console.log(content)
console.log(contentNums)
console.log(contentCodes)
success(Array.from(contentNums));
})
C#互操作调用来源
private IJSRuntime _scriptRuntime = null;
public async Task<dynamic> GetMedia<dynamic>()
{
return await _scriptRuntime.InvokeAsync<dynamic>('AudioFunctions.GetMediaFile');
}
有没有办法将大字节数组或至少字符串从 JS 传递到 Blazor.NET?
看来,使用 ANSI 编码的破解工作正常,我只需要增加 SignalR
消息的大小。
启动
public void ConfigureServices(IServiceCollection services)
{
// ... some other services
services.AddSignalR(o =>
{
o.EnableDetailedErrors = true;
o.MaximumReceiveMessageSize = long.MaxValue;
});
}
JS 互操作
window.InteropFunctions = window.InteropFunctions || {
GetMediaFile: async (classInstance, cssClass) => {
return await new Promise((success, error) => {
const chunks = [];
const recorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
// Event handlers for play and stop to detect when data is available
recorder.addEventListener('stop', {
// Encode data as ANSI string - Windows 1252
const response = new Blob(chunks, { type: 'audio/webm' });
const content = await (new Response(response).arrayBuffer());
const contentNums = new Uint8Array(content);
const contentCodes = new TextDecoder('windows-1252').decode(contentNums);
const audioControl = document.querySelector('.' + cssClass + ' audio');
// Play audio in HTML 5 control
if (audioControl) {
audioControl.src = URL.createObjectURL(response);
}
// Resolve the promise and send data to Blazor.NET
success(contentCodes);
});
// Grab recorded data
recorder.addEventListener('dataavailable', {
if (e.data.size > 0) {
chunks.push(e.data);
}
});
// Record for 5 seconds
recorder.start();
setTimeout(() => recorder.stop(), 5000);
});
}
}
C# 互操作
private IJSRuntime _scriptRuntime = null;
public async Task<string> GetMediaFile<string>(params object[] inputs)
{
return await _scriptRuntime.InvokeAsync<string>('InteropFunctions.GetMediaFile', inputs);
}
从 .NET 发起互操作调用
var instance = DotNetObjectReference.Create(this);
var source = await _audioCommandInstance.GetMediaFile(instance, 'audio-container');
if (string.IsNullOrEmpty(source) == false)
{
var audioBytes = Encoder.GetBytes(source);
await File.WriteAllBytesAsync("audio.wav", audioBytes);
}
我需要使用 Media API in JS, example 为 Blazor 录制一些音频,甚至可能是视频。然后,我想将记录的 Blob
内容从 JS 传递到 Blazor。只要是音频或视频内容,它就可以相当大。
到目前为止我尝试了什么
将数据编码为 ANSI 字符串或传递一个整数数组。这导致
InvalidDataException
、SignalR 断开连接、超时,大约一分钟后 SignalR 恢复正常并且 C# 收到null
将数据编码为 base 64 或传递
UInt8Array
。结果是一样的。直接从 JS 传递
Blob
、ArrayBuffer
或FormData
。这导致 C# 中的空对象ValueKind: {}
。
JS调用来源
recorder.stop();
recorder.exportWAV(async blob => {
const content = await (new Response(blob).arrayBuffer());
const contentNums = new Uint8Array(content);
const contentCodes = new TextDecoder('windows-1252').decode(contentNums);
const data = new FormData();
data.append('file', blob, 'Demo');
//success(window.URL.createObjectURL(blob));
console.log(blob)
console.log(content)
console.log(contentNums)
console.log(contentCodes)
success(Array.from(contentNums));
})
C#互操作调用来源
private IJSRuntime _scriptRuntime = null;
public async Task<dynamic> GetMedia<dynamic>()
{
return await _scriptRuntime.InvokeAsync<dynamic>('AudioFunctions.GetMediaFile');
}
有没有办法将大字节数组或至少字符串从 JS 传递到 Blazor.NET?
看来,使用 ANSI 编码的破解工作正常,我只需要增加 SignalR
消息的大小。
启动
public void ConfigureServices(IServiceCollection services)
{
// ... some other services
services.AddSignalR(o =>
{
o.EnableDetailedErrors = true;
o.MaximumReceiveMessageSize = long.MaxValue;
});
}
JS 互操作
window.InteropFunctions = window.InteropFunctions || {
GetMediaFile: async (classInstance, cssClass) => {
return await new Promise((success, error) => {
const chunks = [];
const recorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
// Event handlers for play and stop to detect when data is available
recorder.addEventListener('stop', {
// Encode data as ANSI string - Windows 1252
const response = new Blob(chunks, { type: 'audio/webm' });
const content = await (new Response(response).arrayBuffer());
const contentNums = new Uint8Array(content);
const contentCodes = new TextDecoder('windows-1252').decode(contentNums);
const audioControl = document.querySelector('.' + cssClass + ' audio');
// Play audio in HTML 5 control
if (audioControl) {
audioControl.src = URL.createObjectURL(response);
}
// Resolve the promise and send data to Blazor.NET
success(contentCodes);
});
// Grab recorded data
recorder.addEventListener('dataavailable', {
if (e.data.size > 0) {
chunks.push(e.data);
}
});
// Record for 5 seconds
recorder.start();
setTimeout(() => recorder.stop(), 5000);
});
}
}
C# 互操作
private IJSRuntime _scriptRuntime = null;
public async Task<string> GetMediaFile<string>(params object[] inputs)
{
return await _scriptRuntime.InvokeAsync<string>('InteropFunctions.GetMediaFile', inputs);
}
从 .NET 发起互操作调用
var instance = DotNetObjectReference.Create(this);
var source = await _audioCommandInstance.GetMediaFile(instance, 'audio-container');
if (string.IsNullOrEmpty(source) == false)
{
var audioBytes = Encoder.GetBytes(source);
await File.WriteAllBytesAsync("audio.wav", audioBytes);
}