Asp.net使用SignalR实现发送图片

 更新时间:2016年04月11日 14:57:52   作者:Learning hard  
这篇文章主要为大家详细介绍了Asp.net使用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编码所增加的内容。

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

        只能通过发送图片的Base64编码的字符串到SignalR服务器,然后服务器再将该Base64字符串推送到需要接收图片的客户端,客户端再使用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="/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发送图片的功能就已经可以运作了。接下来让我们一起看看具体的运行效果到底如何。

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

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

相关文章

  • Asp.net内置对象之Cookies(简介/属性方法/基本操作及实例)

    Asp.net内置对象之Cookies(简介/属性方法/基本操作及实例)

    本文将围绕cookies了解Cookies对象/Cookie对象的属性和方法/Cookie的基本操作及实例:Cookie的写入和读取/Cookie对象相比Session、Application的优缺点扥等,感兴趣的朋友可以了解下,或许对你学习cookies有所帮助
    2013-02-02
  • 详解ASP.NET MVC 解析模板生成静态页(RazorEngine)

    详解ASP.NET MVC 解析模板生成静态页(RazorEngine)

    我们在很多项目开发中会常常用到页面静态化,本篇文章主要介绍了详解ASP.NET MVC 解析模板生成静态页(RazorEngine) ,具有一定的参考价值,有兴趣的可以了解一下。
    2017-03-03
  • repeater、gridview 在绑定时判断判断显示不同的行样式或文本

    repeater、gridview 在绑定时判断判断显示不同的行样式或文本

    repeater、gridview 在绑定时判断判断显示不同的行样式或文本的实现代码,需要的朋友可以参考下。
    2011-09-09
  • LINQ to XML的编程基础

    LINQ to XML的编程基础

    本文介绍了LINQ to XML的编程基础,即System.Xml.Linq命名空间中的多个LINQ to XML类,这些类都是LINQ to XML的支持类,它们使得处理xml比使用其他的xml工具容易得多。在本文中,着重介绍的是XElement、XAttribute和XDocument。
    2010-02-02
  • 为HttpClient添加默认请求报头的四种解决方案

    为HttpClient添加默认请求报头的四种解决方案

    这篇文章主要给大家介绍了关于为HttpClient添加默认请求报头的四种解决方案,文中通过示例代码介绍的非常详细,对大家学习或者使用HttpClient具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • ASP.NET Core处理管道的深入理解

    ASP.NET Core处理管道的深入理解

    这篇文章主要给大家介绍了关于ASP.NET Core处理管道的深入理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Asp.net core程序中使用微软的依赖注入框架

    Asp.net core程序中使用微软的依赖注入框架

    这篇文章介绍了在Asp.net core程序中使用微软的依赖注入框架,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • 详解使用asp.net mvc部分视图渲染html

    详解使用asp.net mvc部分视图渲染html

    为了提升用户体验,一般我们采用ajax加载数据然后根据数据渲染html,渲染html可以使用前端渲染和服务器端渲染,有兴趣的可以了解一下
    2017-07-07
  • asp.net中EXCEL数据导入到数据库的方法

    asp.net中EXCEL数据导入到数据库的方法

    这篇文章主要介绍了asp.net中EXCEL数据导入到数据库的方法,实现读取excel数据并导入到SQL Server数据库的功能,是非常实用的技巧,需要的朋友可以参考下
    2015-01-01
  • .Net8.0 WebApi发布到IIS详细步骤

    .Net8.0 WebApi发布到IIS详细步骤

    本文主要介绍了.Net8.0 WebApi发布到IIS详细步骤, 文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05

最新评论