You can do this with both XSockets and SignalR, but there will be different approaches.
I have been sending images from a Raspberry PI to a webpage with XSockets. I snapped the image when the motion sensor (on the PI) was triggered.
You will probably get better performance with XSockets since there is support for binary frames. So you will not need to send BASE64 encoded strings that are ~36% bigger than the actual image size.
You will also be able to pass metadata along with the binary frame since there are support for that as well in XSockets.
Docs about sending binary data: http://xsockets.net/docs/4/binary-data
I am no SignalR expert, but my guess is that you will BASE64 encode your image and wrap it in JSON since that is what SignalR accepts. If you need help with sending images in SignalR, check out the SignalR room on jabbr https://jabbr.net/#/rooms/signalr
EDIT1: Let me know if you are going for XSockets and need a sample. I can create a really simple sample in that case...
EDIT2: Ok, so I created a simple solution that you can download from my dropbox (for a while). Link: VisualStudio SLN
There is not to much code. If you run it dorectly you will need to have a fodler under c:\temp\images, then just drop images into that folder and they will appear in the browser on every connected client. Notice that you also will get the filename with the message since xsockets support metadata attachments...
FileSystem Watcher
/// <summary>
/// This will be a singleton since the range is internal. You cant connect to this controller.
/// </summary>
[XSocketMetadata("ImageWatcher", PluginRange.Internal)]
public class ImageWatcher : XSocketController
{
private ImageController imageController;
public ImageWatcher()
{
imageController = new ImageController();
var watcher = new FileSystemWatcher
{
Path = @"c:\temp\images\",
NotifyFilter = NotifyFilters.LastWrite,
Filter = "*.jpeg"
};
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
watcher.Changed += watcher_Changed;
watcher.EnableRaisingEvents = true;
}
void watcher_Changed(object sender, FileSystemEventArgs e)
{
try
{
var blob = File.ReadAllBytes(e.FullPath);
var metadata = new { filename = e.Name };
imageController.InvokeToAll(blob, metadata, "newimage");
}
catch
{
}
}
}
Controller
/// <summary>
/// Simple controller that the users will connect to.
/// It does not even have a method in this sample...
///
/// The ImageWatcher class will send images to the clients when you drop a imagein c:\temp\image
/// </summary>
[XSocketMetadata(PluginAlias = "image")]
public class ImageController : XSocketController
{
}
JavaScript/HTML
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<img id="latestImage">
<p id="filename"></p>
<script src="Scripts/XSockets.latest.js"></script>
<script src="Scripts/jquery-2.1.1.js"></script>
<script>
var conn
$(function() {
conn = new XSockets.WebSocket('ws://127.0.0.1:4502', ['image']);
conn.controller('image').on('newimage', function (b) {
console.log(b);
$('#filename').text(b.data.filename);
var uint8Array = new Uint8Array(b.binary);
var arrayBuffer = uint8Array.buffer;
var blob = new Blob([arrayBuffer], { type: "image/jpg" });
var blobUrl = window.URL.createObjectURL(blob);
$("#latestImage").attr("src", blobUrl);
});
});
</script>
</body>
</html>
Thats basically all there is to it. The filesystem watcher is a little weird, but it was just to show you a sample...