首頁  >  文章  >  後端開發  >  Asp.net使用SignalR實作傳送圖片

Asp.net使用SignalR實作傳送圖片

高洛峰
高洛峰原創
2018-05-28 16:22:203164瀏覽

一、引言
  在前一篇已經介紹瞭如何使用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 =
    {
      &#39;0&#39;, &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;7&#39;, &#39;8&#39;, &#39;9&#39;,
      &#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;, &#39;g&#39;, &#39;h&#39;, &#39;i&#39;, &#39;j&#39;, &#39;k&#39;, &#39;l&#39;, &#39;m&#39;, &#39;n&#39;, &#39;o&#39;, &#39;p&#39;, &#39;q&#39;, &#39;r&#39;, &#39;s&#39;, &#39;t&#39;, &#39;u&#39;, &#39;v&#39;,
      &#39;w&#39;, &#39;x&#39;, &#39;y&#39;, &#39;z&#39;,
      &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;I&#39;, &#39;J&#39;, &#39;K&#39;, &#39;L&#39;, &#39;M&#39;, &#39;N&#39;, &#39;O&#39;, &#39;P&#39;, &#39;Q&#39;, &#39;R&#39;, &#39;S&#39;, &#39;T&#39;, &#39;U&#39;, &#39;V&#39;,
      &#39;W&#39;, &#39;X&#39;, &#39;Y&#39;, &#39;Z&#39;
    };
 
    // 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>
  <p class="container">
    <p>用户名:<p id="username"></p></p>
    <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>
  </p>
  <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 = &#39;@Session["username"]&#39;;
      $(&#39;#username&#39;).html(userName);
      // 引用自动生成的集线器代理
      var chat = $.connection.chatHub;
      // 定义服务器端调用的客户端sendMessage来显示新消息
 
      chat.client.sendMessage = function (name, message) {
        // 向页面添加消息
        $(&#39;#discussion&#39;).append(&#39;<li><strong>&#39; + htmlEncode(name)
          + &#39;</strong>: &#39; + htmlEncode(message) + &#39;</li>&#39;);
      };
 
      chat.client.receiveImage = function (name, base64) {
        // 向页面添加消息
        $(&#39;#discussion&#39;).append(&#39;<image class = "file-preview-image" style="width:auto;height:100px;" src=&#39; + base64
          + &#39;/>&#39;);
      };
 
      // 设置焦点到输入框
      $(&#39;#message&#39;).focus();
      // 开始连接服务器
      $.connection.hub.start().done(function () {
        $(&#39;#sendmessage&#39;).click(function () {
          // 调用服务器端集线器的Send方法
          chat.server.send(userName, $(&#39;#message&#39;).val());
          // 清空输入框信息并获取焦点
          $(&#39;#message&#39;).val(&#39;&#39;).focus();
        });
      });
 
      $("#fileinput").fileinput({
        allowedFileExtensions: ["jpg", "png", "gif", "jpeg"],
        maxImageWidth: 700,
        maxImageHeight: 700,
        resizePreference: &#39;height&#39;,
        maxFileCount: 1,
        resizeImage: true
      });
 
      $("#fileinput").on(&#39;fileloaded&#39;, function (event, file, previewId, index, reader) {
        var readers = new FileReader();
        readers.onloadend = function () {
          $(".file-preview-image").attr(&#39;src&#39;, readers.result);
        };
        readers.readAsDataURL(file);
      });
 
      $(&#39;#sendmessage&#39;).click(function() {
        var imagesJson = $(&#39;.file-preview-image&#39;).map(function() {
          var $this = $(this);
          return {
            image: $this.attr(&#39;src&#39;),
            filename: $this.attr(&#39;data-filename&#39;)
          };
        }).toArray();
 
        chat.server.sendImage(userName, imagesJson);
      });
    });
 
  // 为显示的消息进行Html编码
  function htmlEncode(value) {
    var encodedValue = $(&#39;<p />&#39;).text(value).html();
    return encodedValue;
  }
  </script>
   
</body>
</html>

四、運行效果
  經過上面的三步,使用SignalR發送圖片的功能就已經可以運作了。接下來讓我們一起來看看具體的運行效果到底如何。

Asp.net使用SignalR實作傳送圖片

到這裡,本文的所有內容的介紹就結束了,接下來的將介紹如何使用Html5 Notification API 來實現有新消息的提醒功能。

更多Asp.net使用SignalR實現發送圖片相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn