[Asp.net 开发系列之SignalR篇]专题四:使用SignalR实现发送图片
一、引言
在前一篇博文已经介绍了如何使用SignalR来实现聊天室的功能,在这篇文章中,将实现如何使用SignalR来实现发送图片的功能。
二、实现发送图片的思路
我还是按照之前的方式来讲述这篇文章,首先,让我们来理清下实现发送图片功能的思路。
图片的显示,除了直接指定图片的路径外(这种实现方式也称为:http URI schema),还可以通过Data Uri Schema的方式来显示图片。这种方式允许在网页里以字符串形式直接内嵌图片。形式如下所示:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA
7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC" />
上面代码的方式就是Data Url Schema方式来显示图片。关于Data Uri Schema的优缺点有:
- 优点:
可以减少Http请求,因为如果你使用http Uri Schema去指定图片地址的话,这样客户端对每个图片都需要发出Http请求,通过使用Data Uri的方式可以节省带宽和Http请求
缺点:
- IE8以上的版本才支持,且限制大小不可超过32KB。
- 另外Base64的内容会将图片的内容变大33%,但可以通过服务端启用GZIP压缩来减少增大内容。尽管这样,由于发送Http请求会附加很多额外的信息(如Http Header等),这样累计下来一般内容大小还是大于使用Base64编码所增加的内容。
关于更多Data Uri的介绍可以参考百度百科:Data URI
因为SignalR是基于文本方式的传输,所以要实现图片的发送。
- 只能通过发送图片的Base64编码的字符串到SignalR服务器,
- 然后服务器再将该Base64字符串推送到需要接收图片的客户端,
- 客户端再使用Data Uri的方式将图片显示在页面上,从而完成图片的传输。
当然你也可以像Jabbr(一个使用SignalR实现即时聊天的开源项目)那样将图片上传到Azure Bob Table中,然后再将Blob 的Uri 返回所有客户端来显示图片。其实这样的实现方式和我们这里实现类似,客户端可以通过blob的Uri来读取到图片来显示。总之实现思路就是将图片二进制文件的内容间接转换成文本的形式传输。
三、使用SignalR发送图片的实现代码
在具体实现之前,这里需要介绍一个文件上传插件——boostrap-fileinput。该插件用来提供图片的预览功能。关于插件的具体使用可以参考github站点或本文章的实现代码。
- 第一步还是实现我们的集线器
public class ChatHub : Hub
{
/// <summary>
/// 供客户端调用的服务器端代码
/// </summary>
/// <param name="name"></param>
/// <param name="message"></param>
public void Send(string name,string message)
{
// 调用所有客户端的sendMessage方法
Clients.All.sendMessage(name, message);
} // 发送图片
public void SendImage(string name,IEnumerable<ImageData> images)
{
foreach (var item in images ?? Enumerable.Empty<ImageData>())
{
if(String.IsNullOrEmpty(item.Image)) continue;
Clients.All.receiveImage(name, item.Image); // 调用客户端receiveImage方法将图片进行显示
}
} /// <summary>
/// 客户端连接的时候调用
/// </summary>
/// <returns></returns>
public override Task OnConnected()
{
Trace.WriteLine("客户端连接成功");
return base.OnConnected();
}
}
2. HomeController的实现代码,主要为每个客户端生成随机的用户名,再将用户名存入Session中。
public class HomeController : Controller
{
private static readonly char[] Constant =
{
'', '', '', '', '', '', '', '', '', '',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z'
}; // GET: Home
public ActionResult Index()
{
Session["username"] = GenerateRandomName();
return View();
} /// <summary>
/// 产生随机用户名函数
/// </summary>
/// <param name="length">用户名长度</param>
/// <returns></returns>
private static string GenerateRandomName(int length)
{
var newRandom = new System.Text.StringBuilder();
var rd = new Random(DateTime.Now.Millisecond);
for (var i = ; i < length; i++)
{
newRandom.Append(Constant[rd.Next()]);
} return newRandom.ToString();
}
}
3. 接下来就是实现前端页面了。
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>使用SignalR实现发送图片</title>
<link href="/Content/bootstrap.min.css" rel="stylesheet">
<link href="/Content/bootstrap-fileinput/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="container">
<div>用户名:<p id="username"></p></div>
<input type="text" id="message" />
<br/>
<br />
<input id="fileinput" type="file">
<br />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion"></ul>
</div>
<script type="text/javascript" src="~/Scripts/jquery-2.2.2.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/signalr/hubs"></script>
<script src="/Scripts/fileinput.js" type="text/javascript"></script>
<script src="/Scripts/bootstrap.min.js" type="text/javascript"></script>
<script>
$(function () {
var userName = '@Session["username"]';
$('#username').html(userName);
// 引用自动生成的集线器代理
var chat = $.connection.chatHub;
// 定义服务器端调用的客户端sendMessage来显示新消息 chat.client.sendMessage = function (name, message) {
// 向页面添加消息
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
}; chat.client.receiveImage = function (name, base64) {
// 向页面添加消息
$('#discussion').append('<image class = "file-preview-image" style="width:auto;height:100px;" src=' + base64
+ '/>');
}; // 设置焦点到输入框
$('#message').focus();
// 开始连接服务器
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// 调用服务器端集线器的Send方法
chat.server.send(userName, $('#message').val());
// 清空输入框信息并获取焦点
$('#message').val('').focus();
});
}); $("#fileinput").fileinput({
allowedFileExtensions: ["jpg", "png", "gif", "jpeg"],
maxImageWidth: 700,
maxImageHeight: 700,
resizePreference: 'height',
maxFileCount: 1,
resizeImage: true
}); $("#fileinput").on('fileloaded', function (event, file, previewId, index, reader) {
var readers = new FileReader();
readers.onloadend = function () {
$(".file-preview-image").attr('src', readers.result);
};
readers.readAsDataURL(file);
}); $('#sendmessage').click(function() {
var imagesJson = $('.file-preview-image').map(function() {
var $this = $(this);
return {
image: $this.attr('src'),
filename: $this.attr('data-filename')
};
}).toArray(); chat.server.sendImage(userName, imagesJson);
});
}); // 为显示的消息进行Html编码
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script> </body>
</html>
四、运行效果
经过上面的三步,使用SignalR发送图片的功能就已经可以运作了。接下来让我们一起看看具体的运行效果到底如何。

五、总结
到这里,本文的所有内容的介绍就结束了,接下来的将介绍如何使用Html5 Notification API 来实现有新消息的提醒功能。
本文所有源码下载地址:SignalRSendFile
[Asp.net 开发系列之SignalR篇]专题四:使用SignalR实现发送图片的更多相关文章
- [Asp.net 开发系列之SignalR篇]专题五:SignalR支持的平台
SignalR支持多种服务器和客户端配置.此外,每种传输方式都有自身的要求限制:如果某种传输方式不被系统支持,SignalR能够优雅地将故障转移到其他类型的传输方式.关于SignalR所支持的传输方式 ...
- 【Windows10 IoT开发系列】配置篇
原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry ...
- openlayers5-webpack 入门开发系列一初探篇(附源码下载)
前言 openlayers5-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载 ...
- leaflet-webpack 入门开发系列一初探篇(附源码下载)
前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...
- SpringBoot系列教程web篇Listener四种注册姿势
java web三要素Filter, Servlet前面分别进行了介绍,接下来我们看一下Listener的相关知识点,本篇博文主要内容为SpringBoot环境下,如何自定义Listener并注册到s ...
- [Asp.net 开发系列之SignalR篇]专题六:使用SignalR实现消息提醒
一.引言 前面一篇文章我介绍了如何使用SignalR实现图片的传输,然后对于即时通讯应用来说,消息提醒是必不可少的.现在很多网站的都有新消息的提醒功能.自然对于SignalR系列也少不了这个功能的实现 ...
- [Asp.net 开发系列之SignalR篇]专题一:Asp.net SignalR快速入门
一.前言 之前半年时间感觉自己有点浮躁,导致停顿了半年多的时间没有更新博客,今天重新开始记录博文,希望自己可以找回初心,继续沉淀.由于最近做的项目中用到SignalR技术,所以打算总结下Asp.net ...
- [置顶]【实用 .NET Core开发系列】- 导航篇
前言 此系列从出发点来看,是 上个系列的续篇, 上个系列因为后面工作的原因,后面几篇没有写完,后来.NET Core出来之后,注意力就转移到了.NET Core上,所以再也就没有继续下去,此是原因之一 ...
- openlayers4 入门开发系列之风场图篇
前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...
随机推荐
- Spring @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
背景 昨天一个人瞎倒腾spring boot,然后遇到了一点问题,所以把这个问题总结一下. 主要讲解request 数据到handler method 参数数据的绑定,所用到的注解和什么情形下使用. ...
- 关闭ctrl+shift+d截图
关闭ctrl+shift+d截图,最近用sublime text3的时候,用ctrl+shift+d,总是跳出来截图,找了半天,原来是百度浏览器的截图功能快捷键是ctrl+shift+d, 关掉即可
- 快速排序 - C语言
看了这本<数据结构与算法分析>中的快速排序. 写下自己理解后的代码,以备后用. #include "stdio.h" void insertSort(int arr[] ...
- maven下读取资源文件的问题(转)
原文链接:http://shenchao.me/2016/04/20/maven%E4%B8%8B%E8%AF%BB%E5%8F%96%E8%B5%84%E6%BA%90%E6%96%87%E4%BB ...
- CSS3制作各种形状图像
圆形-椭圆形-三角形-倒三角形=左三角形-右三角形-菱形-平行四边形- 星形-六角星形-五边形-六边形-八角形-心形-蛋形-无穷符号-消息提示框 不废话直接 html界面(亲测的) ------转自百 ...
- 【SQLServer】“无法对数据库’XXX’ 执行删除,因为它正用于复制”的解决方法
警告: 一个或多个现有列的 ANSI_PADDING 设置为 "off",将以 ANSI_PADDING 为 "on" 的设置重新创建 [SQLServer]& ...
- 浅析 IDE跟编译器
之前听别人总说你用啥IDE,直接用编译器. 总的来说IDE包含编译器,而编译器仅仅是IDE的一部分, IDE包括编辑器与编译器. IDE: 可以在IDE上面编写代码,然后编译运行,有错误还能调试.比如 ...
- 通俗易懂的 JSon解析处理
1.主要用到的类: 主要用到了JavaScriptSerializer类,该类在System.Web.Script.Serialization命名空间(在System.Web.Extensions.d ...
- JavaScript中对象的含义与this的指向
JavaScript中的对象:无序属性的集合 -其属性可以包含基本值.对象或函数.对象就是一组没有顺序的值.我们可以吧JavaScript中的对象想象成键值对,其中值可以是数据和函数.对象的行为和特征 ...
- 配置nginx负载均衡
配置nginx负载均衡 执行命令:vi /usr/local/nginx/sbin/nginx/conf/nginx.conf 修改为: worker_processes 2; events { ...