[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 官网在线例子 ...
随机推荐
- Linux中的输入重定向,变量
1 :分号 格式:命令1:命令2;命令3 说明:命令之间用分号隔开是顺序执行,命令之间没有任何逻辑关系 2 && 逻辑与 格式:命令1 && 命令2 说明:命令1正 ...
- tinymce整合struts2使用
在提交之前记得 instance.post(); 这个应付老师检查还是可以的,但是很详细的怎么具体使用,还是要去看官方文档. <%@ page language="java" ...
- linux环境下jdk的安装步骤
JDK的安装步骤:1. 把jdk文件cp到服务器上2. 加权限 chmod +x 文件3. 执行 ./4.修改配置 vi /etc/profile 最后一行添加:export JAVA_HOME=/ ...
- simplexml_load_string 解析xml
<?php //simplexml_load_string 解析两种类型的xml $res='<?xml version="1.0" encoding="UT ...
- IOS 本地推送 IOS10.0以上 static的作用 const的作用
//需要在AppDelegate里面启动APP的函数 加上 UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNot ...
- 如果因特网中的所有链路都提供可靠的交付服务,TCP可靠传输服务是多余的吗?
IP协议因为是无连接的, 所以其传输是不可靠的.虽然链路保证了数据包在端到端的传输中不发生差错,但是它不能保证IP数据包是按照正确的书需到达最终的目的地.IP数据包可以使用不同的路由通过网络,到达接收 ...
- 实验 2 用C语言编写简单程序
#include<stdio.h> int main() { int x,y; printf("enter x:"); scanf("%d",&am ...
- noip2008-t3
[题目描述] 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸 ...
- ArcGIS API中FindTask中文搜索无效,服务器编码问题URIEncoding="utf-8"
问题来源:字符编码问题导致ArcMap中字符乱码或显示不正常,因而在F:\Program Files\ArcGIS\Server\framework\runtime\tomcat\conf中serve ...
- Extjs4.2或以上 使用自定义事件时报错问题
最近使用了extjs 自定义事件模型,代码如下: function Person(name) { this.name = name; this.addEvents('walk'); } Ext.ext ...