如何从 dotnet 核心中的服务器向 SignalR 客户端发送二进制文件
how to send a binary file to SignalR client from server in dotnet core
我们有一个使用 .Net 将文件发送到 SignalR 客户端的解决方案
我们现在已经转移到 .Net Core
在以前的 .net 解决方案中,我们过去常常通过 GlobalHost.ConnectionManager
访问 Hub 上下文
var myHub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
myHub.Clients.Client(connectionId).doStuffWithFile(fileByteArray, fileName);
在客户端,函数 doStuffWithFile
会被两个参数触发。
在 new .Net Core 解决方案中,我通过派生自 Hub 创建了一个 Hub class。我添加了一种发送方法来将文件发送到特定客户端而不是将其广播给每个人
public class MyHub : Hub
{
private static string _connectionId;
public override Task OnConnectedAsync()
{
_connectionId = Context.ConnectionId;
return Task.CompletedTask;
}
public override Task OnDisconnectedAsync(Exception exception)
{
_connectionId = Context.ConnectionId;
//// remove Connection Id
return base.OnDisconnectedAsync(exception);
}
public async Task Send(byte[] fileByteArray, string fileName)
{
await Clients.Client(_connectionId).InvokeAsync("doStuff", fileByteArray, fileName);
}
}
但是,我在 .Net 核心中没有任何机制(例如 GlobalHost 或 ConnectionManager)来获取 HubContext 来发送文件。
在客户端:
static void Main(string[] args)
{
var connection = new HubConnectionBuilder()
.WithUrl("http://localhost:25786/file")
.WithConsoleLogger()
.Build();
connection.On<byte[], string>("doStuff", DoStuff);
connection.StartAsync().ContinueWith(
task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Connection faulty");
}
});
Console.ReadLine();
}
private static void DoStuff(byte[] data, string name)
{
File.WriteAllBytes(@"c:\Projects\" + name, data);
}
我试图创建一个新的 MyHub 实例来调用 Send 方法,但它根本不起作用。你能告诉我怎么做吗?
这不是您问题的直接答案,但希望它能帮助您找到解决方案。
将连接 ID 存储在静态 class 变量中是不正确的。每次新客户端连接时它都会更改,您将无法控制要发送给哪个客户端。从您提供的代码中不清楚您如何知道将文件发送到哪个客户端。请注意,当客户端断开连接时,您还设置了 _connectionId
,因此您可能会尝试将数据发送到您知道已关闭的连接。我实际上认为您会希望将目标连接 ID 或用户传递给集线器 Send
方法。我认为您在集线器方法本身中可能没有足够的上下文来解析连接 ID,但由于连接 ID 是一个 SignalR 概念,因此可能很难在 SignalR 组件之外访问它。这就是为什么使用用户而不是连接 ID 可能更容易(即 Clients.User(...)
而不是 Clients.Client(...
)。
GlobalHost
不再存在于新的 SignalR 中。相反,您可以将 IHubContext<THub>
注入要从中调用方法的 class 并使用 InvokeAsync
。 Here 是从 Mvc 控制器调用集线器方法的示例。
我们有一个使用 .Net 将文件发送到 SignalR 客户端的解决方案
我们现在已经转移到 .Net Core
在以前的 .net 解决方案中,我们过去常常通过 GlobalHost.ConnectionManager
var myHub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
myHub.Clients.Client(connectionId).doStuffWithFile(fileByteArray, fileName);
在客户端,函数 doStuffWithFile
会被两个参数触发。
在 new .Net Core 解决方案中,我通过派生自 Hub 创建了一个 Hub class。我添加了一种发送方法来将文件发送到特定客户端而不是将其广播给每个人
public class MyHub : Hub
{
private static string _connectionId;
public override Task OnConnectedAsync()
{
_connectionId = Context.ConnectionId;
return Task.CompletedTask;
}
public override Task OnDisconnectedAsync(Exception exception)
{
_connectionId = Context.ConnectionId;
//// remove Connection Id
return base.OnDisconnectedAsync(exception);
}
public async Task Send(byte[] fileByteArray, string fileName)
{
await Clients.Client(_connectionId).InvokeAsync("doStuff", fileByteArray, fileName);
}
}
但是,我在 .Net 核心中没有任何机制(例如 GlobalHost 或 ConnectionManager)来获取 HubContext 来发送文件。
在客户端:
static void Main(string[] args)
{
var connection = new HubConnectionBuilder()
.WithUrl("http://localhost:25786/file")
.WithConsoleLogger()
.Build();
connection.On<byte[], string>("doStuff", DoStuff);
connection.StartAsync().ContinueWith(
task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Connection faulty");
}
});
Console.ReadLine();
}
private static void DoStuff(byte[] data, string name)
{
File.WriteAllBytes(@"c:\Projects\" + name, data);
}
我试图创建一个新的 MyHub 实例来调用 Send 方法,但它根本不起作用。你能告诉我怎么做吗?
这不是您问题的直接答案,但希望它能帮助您找到解决方案。
将连接 ID 存储在静态 class 变量中是不正确的。每次新客户端连接时它都会更改,您将无法控制要发送给哪个客户端。从您提供的代码中不清楚您如何知道将文件发送到哪个客户端。请注意,当客户端断开连接时,您还设置了 _connectionId
,因此您可能会尝试将数据发送到您知道已关闭的连接。我实际上认为您会希望将目标连接 ID 或用户传递给集线器 Send
方法。我认为您在集线器方法本身中可能没有足够的上下文来解析连接 ID,但由于连接 ID 是一个 SignalR 概念,因此可能很难在 SignalR 组件之外访问它。这就是为什么使用用户而不是连接 ID 可能更容易(即 Clients.User(...)
而不是 Clients.Client(...
)。
GlobalHost
不再存在于新的 SignalR 中。相反,您可以将 IHubContext<THub>
注入要从中调用方法的 class 并使用 InvokeAsync
。 Here 是从 Mvc 控制器调用集线器方法的示例。