视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Asp.net使用SignalR实现发送图片
2020-11-27 22:37:46 责编:小采
文档


一、引言
  在前一篇已经介绍了如何使用SignalR来实现聊天室的功能,在这篇文章中,将实现如何使用SignalR来实现发送图片的功能。

二、实现发送图片的思路
  我还是按照之前的方式来讲述这篇文章,首先,让我们来理清下实现发送图片功能的思路。

  图片的显示,除了直接指定图片的路径外(这种实现方式也称为:http URI schema),还可以通过Data Uri Schema的方式来显示图片。这种方式允许在网页里以字符串形式直接内嵌图片。形式如下所示:

代码如下:<img src="data:image/png;base,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA
7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC" />
  上面代码的方式就是Data Url Schema方式来显示图片。关于Data Uri Schema的优缺点有:

优点:
  可以减少Http请求,因为如果你使用http Uri Schema去指定图片地址的话,这样客户端对每个图片都需要发出Http请求,通过使用Data Uri的方式可以节省带宽和Http请求

缺点:

  IE8以上的版本才支持,且大小不可超过32KB。
  另外Base的内容会将图片的内容变大33%,但可以通过服务端启用GZIP压缩来减少增大内容。尽管这样,由于发送Http请求会附加很多额外的信息(如Http Header等),这样累计下来一般内容大小还是大于使用Base编码所增加的内容。

  因为SignalR是基于文本方式的传输,所以要实现图片的发送。

        只能通过发送图片的Base编码的字符串到SignalR服务器,然后服务器再将该Base字符串推送到需要接收图片的客户端,客户端再使用Data Uri的方式将图片显示在页面上,从而完成图片的传输。
  当然你也可以像Jabbr(一个使用SignalR实现即时聊天的开源项目)那样将图片上传到Azure Bob Table中,然后再将Blob 的Uri 返回所有客户端来显示图片。其实这样的实现方式和我们这里实现类似,客户端可以通过blob的Uri来读取到图片来显示。总之实现思路就是将图片二进制文件的内容间接转换成文本的形式传输。

三、使用SignalR发送图片的实现代码
  在具体实现之前,这里需要介绍一个文件上传插件——boostrap-fileinput。该插件用来提供图片的预览功能。关于插件的具体使用可以参考github站点或本文章的实现代码。

1、实现我们的集线器

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 =
 {
 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 '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(4);
 return View();
 }

 /// <summary>
 /// 产生随机用户名函数
 /// </summary>
 /// <param name="length">用户名长度</param>
 /// <returns></returns>
 private static string GenerateRandomName(int length)
 {
 var newRandom = new System.Text.StringBuilder(62);
 var rd = new Random(DateTime.Now.Millisecond);
 for (var i = 0; i < length; i++)
 {
 newRandom.Append(Constant[rd.Next(62)]);
 }

 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="https://www.gxlcms.com/Scripts/fileinput.js" type="text/javascript"></script>
 <script src="https://www.gxlcms.com/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, base) {
 // 向页面添加消息
 $('#discussion').append('<image class = "file-preview-image" style="width:auto;height:100px;" src=' + base
 + '/>');
 };

 // 设置焦点到输入框
 $('#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发送图片的功能就已经可以运作了。接下来让我们一起看看具体的运行效果到底如何。

源码下载:Asp.net使用SignalR实现发送图片

到这里,本文的所有内容的介绍就结束了,接下来的将介绍如何使用Html5 Notification API 来实现有新消息的提醒功能。

下载本文
显示全文
专题