SignalR in .NET Core - File Downloads
Written on July 1st , 2018 by José Maia
This is just a small example of how to use the new SignalR version distributed with .NET Core from 2.1 onwards in order to perform a file download between a client and a server.
The usage scenario here was a server with a Web API/MVC logic that hosts a SignalR hub, combined with a series of clients that exist in machines distributed across the world that are connected to that hub. It should be possible for the hub to trigger a file download on those clients, sending them a zip, or a JPG, or whatever.
This sample is of the server-side code:
public ChannelReader<byte[]> DownloadFileStream(string path)
{
Guard.Against<FileNotFoundException>(!File.Exists(path), $"No file found at {path}");
var channel = Channel.CreateUnbounded<byte[]>();
_ = WriteToChannel(channel, path);
return channel.Reader;
async Task WriteToChannel(ChannelWriter<byte[]> writer, string filePath)
{
using (FileStream fs = File.OpenRead(filePath))
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = await fs.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await writer.WriteAsync(buffer);
await Task.Delay(1000);
}
writer.Complete();
}
}
}
And on the client-side:
private async Task BeginStreamingFile(string path)
{
string fileName = Path.GetFileName(path);
var channel = await _connection.StreamAsChannelAsync<byte[]>("DownloadFileStream", path, CancellationToken.None);
while (await channel.WaitToReadAsync())
{
using (FileStream fs = File.OpenWrite(fileName)) {
while (channel.TryRead(out byte[] buffer))
{
await fs.WriteAsync(buffer, 0, buffer.Length);
}
}
}
}
The solution I had to begin the streaming was for the client to get a message with the path of the file it wanted to download from a helper method in a controller I’d do a HTTP POST on. Before I was able to develop something cleverer, we decided that, for the purposes of the feature we were designing, we could just use a feature we already had designed and do the download of a ZIP file from the API with what we needed. Hopefully in the future we’ll come back to this!
References / Read More
- https://radu-matei.com/blog/signalr-core/ - Please check out Radu Matei’s post on ASP.NET SignalR. It was really helpful in getting us started with it, especially as we began this work before a stable version of .NET Core 2.1 was even out, so the documentation didn’t cover a lot of what we needed.