H5+MUI+Node.js+Socket.io实现即时聊天以及发送+图片压缩

Posted 云上人间钦自赏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H5+MUI+Node.js+Socket.io实现即时聊天以及发送+图片压缩相关的知识,希望对你有一定的参考价值。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<title></title>
		<link href="css/mui.min.css" rel="stylesheet" />
		<!--<link rel="stylesheet" type="text/css" href="css/app.css" />-->
		<link href="css/mui.imageviewer.css" rel="stylesheet" />//发送图片后,点击图片大图预览用的
		<link rel="stylesheet" href="css/iconfont.css">
			
		<!–[if lt IE 8]><script src="js/json3.js"></script><![endif]–> 
		<style type="text/css">
			.mui-bar-nav {
				background-color: #00abed;
				-webkit-box-shadow: none;
				box-shadow: none;
			}
			.mui-bar {
				height: 80px;
				line-height: 80px;
			}
			.mui-title {
				color: #fff;
				font-weight: bold;
			}
			.msg-my-img{
				float: right;
				width: 38px;
				height: 38px;
				border-radius: 3px;
				color: #ddd;
				vertical-align: top;
				text-align: center;
			}
		</style>
		<style>
			html,
			body {
				height: 100%;
				margin: 0px;
				padding: 0px;
				overflow: hidden;
				-webkit-touch-callout: none;
				-webkit-user-select: none;
			}
			footer {
				position: fixed;
				width: 100%;
				height: 50px;
				min-height: 50px;
				border-top: solid 1px #bbb;
				left: 0px;
				bottom: 0px;
				overflow: hidden;
				padding: 0px 50px;
				background-color: #fafafa;
			}
			.footer-left {
				position: absolute;
				width: 50px;
				height: 50px;
				left: 0px;
				bottom: 0px;
				text-align: center;
				vertical-align: middle;
				line-height: 100%;
				padding: 12px 4px;
			}
			.footer-right {
				position: absolute;
				width: 50px;
				height: 50px;
				right: 0px;
				bottom: 0px;
				text-align: center;
				vertical-align: middle;
				line-height: 100%;
				padding: 12px 5px;
				padding-top:15px;
				display: inline-block;
			}
			.footer-center {
				height: 100%;
				
				padding: 5px 0px;
				position: absolute;
				left:50px;
				right: 50px;
			}
			.footer-center [class*=input] {
				width: 100%;
				height: 100%;
				border-radius: 5px;
			}
			.footer-center .input-text {
				background: #fff;
				border: solid 1px #ddd;
				padding: 10px !important;
				font-size: 16px !important;
				line-height: 18px !important;
				font-family: verdana !important;
				overflow: hidden;
			}
			.footer-center .input-sound {
				background-color: #eee;
			}
			.mui-content {
				height: 100%;
				padding: 44px 0px 50px 0px;
				overflow: auto;
				background-color: #eaeaea;
			}
			#msg-list {
				height: 100%;
				overflow: auto;
				-webkit-overflow-scrolling: touch;
			}
			.msg-item {
				padding: 8px;
				clear: both;
			}
			.msg-item .mui-item-clear {
				clear: both;
			}
			.msg-item .msg-user {
				width: 38px;
				height: 38px;
				border: solid 1px #d3d3d3;
				display: inline-block;
				background: #fff;
				border-radius: 3px;
				vertical-align: top;
				text-align: center;
				float: left;
				padding: 3px;
				color: #ddd;
			}
			
			.msg-item .msg-user-img{
				width: 38px;
				height: 38px;
				display: inline-block;
				border-radius: 3px;
				vertical-align: top;
				text-align: center;
				float: left;
				color: #ddd;
			}
			
			.msg-item .msg-content {
				display: inline-block;
				border-radius: 5px;
				border: solid 1px #d3d3d3;
				background-color: #FFFFFF;
				color: #333;
				padding: 8px;
				vertical-align: top;
				font-size: 15px;
				position: relative;
				margin: 0px 8px;
				max-width: 75%;
				min-width: 35px;
				float: left;
				word-break:break-all;
			}
			.msg-item .msg-content .msg-content-inner {
				overflow-x: hidden;
			}
			.msg-item .msg-content .msg-content-arrow {
				position: absolute;
				border: solid 1px #d3d3d3;
				border-right: none;
				border-top: none;
				background-color: #FFFFFF;
				width: 10px;
				height: 10px;
				left: -5px;
				top: 12px;
				-webkit-transform: rotateZ(45deg);
				transform: rotateZ(45deg);
			}
			.msg-item-self .msg-user,
			.msg-item-self .msg-content {
				float: right;
			}
			.msg-item-self .msg-content .msg-content-arrow {
				left: auto;
				right: -5px;
				-webkit-transform: rotateZ(225deg);
				transform: rotateZ(225deg);
			}
			.msg-item-self .msg-content,
			.msg-item-self .msg-content .msg-content-arrow {
				background-color: #4CD964;
				color: #fff;
				border-color: #2AC845;
				word-break:break-all;
			}
			footer .mui-icon {
				color: #000;
			}
			footer .mui-icon:active {
				color: #007AFF !important;
			}
			footer .mui-icon-paperplane:before {
				content: "发送";
			}
			footer .mui-icon-paperplane {
				/*-webkit-transform: rotateZ(45deg);
				transform: rotateZ(45deg);*/
				
				font-size: 16px;
				word-break: keep-all;
				line-height: 100%;
				padding-top: 6px;
				color: rgba(0, 135, 250, 1);
				font-style: normal;
			}
			#msg-sound {
				-webkit-user-select: none !important;
				user-select: none !important;
			}
			.rprogress {
				position: absolute;
				left: 50%;
				top: 50%;
				width: 140px;
				height: 140px;
				margin-left: -70px;
				margin-top: -70px;
				background-image: url(../images/arecord.png);
				background-repeat: no-repeat;
				background-position: center center;
				background-size: 30px 30px;
				background-color: rgba(0, 0, 0, 0.7);
				border-radius: 5px;
				display: none;
				-webkit-transition: .15s;
			}
			.rschedule {
				background-color: rgba(0, 0, 0, 0);
				border: 5px solid rgba(0, 183, 229, 0.9);
				opacity: .9;
				border-left: 5px solid rgba(0, 0, 0, 0);
				border-right: 5px solid rgba(0, 0, 0, 0);
				border-radius: 50px;
				box-shadow: 0 0 15px #2187e7;
				width: 46px;
				height: 46px;
				position: absolute;
				left: 50%;
				top: 50%;
				margin-left: -23px;
				margin-top: -23px;
				-webkit-animation: spin 1s infinite linear;
				animation: spin 1s infinite linear;
			}
			.r-sigh{
				display: none;
				border-radius: 50px;
				box-shadow: 0 0 15px #2187e7;
				width: 46px;
				height: 46px;
				position: absolute;
				left: 50%;
				top: 50%;
				margin-left: -23px;
				margin-top: -23px;
				text-align: center;
				line-height: 46px;
				font-size: 40px;
				font-weight: bold;
				color: #2187e7;
			}
			.rprogress-sigh{
				background-image: none !important;
			}
			.rprogress-sigh .rschedule{
				display: none !important;
			}
			.rprogress-sigh .r-sigh{
				display: block !important;
			}
			.rsalert {
				font-size: 12px;
				color: #bbb;
				text-align: center;
				position: absolute;
				border-radius: 5px;
				width: 130px;
				margin: 5px 5px;
				padding: 5px;
				left: 0px;
				bottom: 0px;
			}
			@-webkit-keyframes spin {
				0% {
					-webkit-transform: rotate(0deg);
				}
				100% {
					-webkit-transform: rotate(360deg);
				}
			}
			@keyframes spin {
				0% {
					transform: rotate(0deg);
				}
				100% {
					transform: rotate(360deg);
				}
			}
			#h {
				background: #fff;
				border: solid 1px #ddd;
				padding: 10px !important;
				font-size: 16px !important;
				font-family: verdana !important;
				line-height: 18px !important;
				overflow: visible;
				position: absolute;
				left: -1000px;
				right: 0px;
				word-break: break-all;
				word-wrap: break-word;
			}
			.cancel {
				background-color: darkred;
			}
		</style>
	</head>

	<body contextmenu="return false;">
		<header class="mui-bar mui-bar-nav">
			<div style="margin-top:30px;">
			<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left" style="color: #fff;font-size: 26px;"></a>
			<h1 class="mui-title"><span id="name"></span></h1>
			</div>
		</header>
		<pre id='h'></pre>
		<script id='msg-template' type="text/template">
			<% for(var i in record){ var item=record[i]; %>
				<div class="msg-item <%= (item.sender=='self'?' msg-item-self':'') %>" msg-type='<%=(item.type)%>' msg-content='<%=(item.content)%>'>
					<div style="height: 30px;text-align: center;font-size: small;color: #a6a6a6;"><%=item.addtime %></div>
					<% if(item.sender=='self' ) { %>
						<!--<i class="msg-user mui-icon mui-icon-person"></i>-->
						<img class="msg-my-img" src="<%=item.upic%>" alt="" />
					<% } else { %>
						<img class="msg-user-img" src="<%=item.upic%>" alt="" />
					<% } %>
					<div class="msg-content">
						<div class="msg-content-inner">
							<% if(item.type=='text' ) { %>
								<%=( item.content|| '  ') %>
							<% } else if(item.type=='image' ) { %>
								<img class="msg-content-image" src="<%=(item.content)%>" style="max-width: 100px;" />
							<% } else if(item.type=='sound' ) { %>
								<span class="mui-icon iconfont icon-yuyin" style="font-size: 18px;font-weight: bold;"></span>
								<span class="play-state">点击播放</span>
							<% } %>
						</div>
						<div class="msg-content-arrow"></div>
					</div>
					<div class="mui-item-clear"></div>
				</div>
			<% } %>
		</script>
		<div class="mui-content" style="padding-top:70px;">
			<div id='msg-list'>
			</div>
		</div>
		<footer>
			<div class="footer-left">
				<i id='msg-image' class="mui-icon iconfont icon-paizhao" style="font-size: 28px;"></i>
			</div>
			<div class="footer-center">
				<textarea id='msg-text' type="text" class='input-text'></textarea>
				<button id='msg-sound' type="button" class='input-sound' style="display: none;">按住说话</button>
			</div>
			<label for="" class="footer-right">
				<i id='msg-type' class="mui-icon-paperplane"></i>
				<!--<i id='msg-type' class="mui-icon mui-icon-mic"></i>-->
			</label>
		</footer>
		<div id='sound-alert' class="rprogress">
			<div class="rschedule"></div>
			<div class="r-sigh">!</div>
			<div id="audio_tips" class="rsalert">手指上滑,取消发送</div>
		</div>
		<script src="js/mui.min.js"></script>
		<script src="js/mui.imageViewer.js"></script>
		<script src="js/arttmpl.js"></script>
		<script src="js/db.js"></script>//创建数据库的一些操作
		<script src="js/login.js" type="text/javascript" charset="utf-8"></script>//登录成功后记录的一些个人信息
		<script src="http://10.0.1.0:65535/socket.io/socket.io.js"></script>//服务端
		<script type="text/javascript" charset="utf-8">
			mui.init({
				beforeback:function(){
					localStorage.chartitem="none";
				}
			})
		
			var ws=null;
			var code,name,onlineUsers2;
			//var bindMsgList;
			(function($, doc) {
				var MIN_SOUND_TIME = 800;
				$.init({
					gestureConfig: {
						tap: true, //默认为true
						doubletap: true, //默认为false
						longtap: true, //默认为false
						swipe: true, //默认为true
						drag: true, //默认为true
						hold: true, //默认为false,不监听
						release: true //默认为false,不监听
					}
				});
				template.config('escape', false);
				$.plusReady(function() {
					//去掉滚动条
					plus.webview.currentWebview().setStyle({
						scrollIndicator: 'none'  
					});
					ws = plus.webview.currentWebview();
					code = ws.account;//警号 
					name=ws.name;//姓名
					localStorage.chartitem="show";
					
					document.getElementById("name").innerText=plus.webview.currentWebview().name;
					plus.webview.currentWebview().setStyle({
						softinputMode: "adjustResize"
					});
					var showKeyboard = function() {
						if ($.os.ios) {
							var webView = plus.webview.currentWebview().nativeInstanceObject();
							webView.plusCallMethod({
								"setKeyboardDisplayRequiresUserAction": false
							});
						} else {
							var Context = plus.android.importClass("android.content.Context");
							var InputMethodManager = plus.android.importClass("android.view.inputmethod.InputMethodManager");
							var main = plus.android.runtimeMainActivity();
							var imm = main.getSystemService(Context.INPUT_METHOD_SERVICE);
							imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
							//var view = ((ViewGroup)main.findViewById(android.R.id.content)).getChildAt(0);
							imm.showSoftInput(main.getWindow().getDecorView(), InputMethodManager.SHOW_IMPLICIT);
						}
					};
					var record =[];
					var ui = {
						body: doc.querySelector('body'),
						footer: doc.querySelector('footer'),
						footerRight: doc.querySelector('.footer-right'),
						footerLeft: doc.querySelector('.footer-left'),
						btnMsgType: doc.querySelector('#msg-type'),
						boxMsgText: doc.querySelector('#msg-text'),
						boxMsgSound: doc.querySelector('#msg-sound'),
						btnMsgImage: doc.querySelector('#msg-image'),
						areaMsgList: doc.querySelector('#msg-list'),
						boxSoundAlert: doc.querySelector('#sound-console.log'),
						h: doc.querySelector('#h'),
						content: doc.querySelector('.mui-content')
					};
					ui.h.style.width = ui.boxMsgText.offsetWidth + 'px';
					//console.log(ui.boxMsgText.offsetWidth );
					var footerPadding = ui.footer.offsetHeight - ui.boxMsgText.offsetHeight;
					var msgItemTap = function(msgItem, event) {
						var msgType = msgItem.getAttribute('msg-type');
						var msgContent = msgItem.getAttribute('msg-content')
						if (msgType == 'sound') {
							player = plus.audio.createPlayer(msgContent);
							var playState = msgItem.querySelector('.play-state');
							playState.innerText = '正在播放...';
							player.play(function() {
								playState.innerText = '点击播放';
							}, function(e) {
								playState.innerText = '点击播放';
							});
						}
					};
					var imageViewer = new $.ImageViewer('.msg-content-image', {
						dbl: false
					});
					var bindMsgList = function() {
						//绑定数据:
						ui.areaMsgList.innerHTML = template('msg-template', {
							"record": record
						});
						var msgItems = ui.areaMsgList.querySelectorAll('.msg-item');
						[].forEach.call(msgItems, function(item, index) {
							item.addEventListener('tap', function(event) {
								msgItemTap(item, event);
							}, false);
						});
						imageViewer.findAllImage();
						setTimeout(function(){
							ui.areaMsgList.scrollTop = ui.areaMsgList.scrollHeight + ui.areaMsgList.offsetHeight;	
						},500);
					};
					
					bindMsgList();
					window.addEventListener('resize', function() {
						ui.areaMsgList.scrollTop = ui.areaMsgList.scrollHeight + ui.areaMsgList.offsetHeight;
					}, false);
					var send = function(msg) {
						record.push(msg);
						bindMsgList();
					};
					var toRobot = function(info) {
						bindMsgList();
					};

					function msgTextFocus() {
							ui.boxMsgText.focus();
							setTimeout(function() {
								ui.boxMsgText.focus();
							}, 150);
						}
						//解决长按“发送”按钮,导致键盘关闭的问题;
					ui.footerRight.addEventListener('touchstart', function(event) {
						
						if (ui.btnMsgType.classList.contains('mui-icon-paperplane')) {
							msgTextFocus();
							event.preventDefault();
						}
					});
					//解决长按“发送”按钮,导致键盘关闭的问题;
					ui.footerRight.addEventListener('touchmove', function(event) {
						if (ui.btnMsgType.classList.contains('mui-icon-paperplane')) {
							msgTextFocus();
							event.preventDefault();
						}
					});
					ui.footerRight.addEventListener('release', function(event) {
						//
						if(ui.boxMsgText.value.length<1){
							//mui.toast("近期开放");
							return;
						}
						
						if (ui.btnMsgType.classList.contains('mui-icon-paperplane')) {
							//showKeyboard();
							ui.boxMsgText.focus();
							setTimeout(function() {
								ui.boxMsgText.focus();
							}, 150);
							//							event.detail.gesture.preventDefault();
							
							//接收服务器端显示,取代本地显示
							/*send({
								sender: 'self',
								type: 'text',
								content: ui.boxMsgText.value.replace(new RegExp('\n', 'gm'), '<br/>')
							});*/
							var content=ui.boxMsgText.value.replace(new RegExp('\n', 'gm'), '<br/>');
							ui.boxMsgText.value = '';
							$.trigger(ui.boxMsgText, 'input', null);
							
							//console.log(plus.webview.currentWebview().account+"ee");
							//同步内容
							CHAT.submit(content,plus.webview.currentWebview().account);//接收者
							
						} else if (ui.btnMsgType.classList.contains('icon-yuyin')) {
							ui.btnMsgType.classList.add('icon-xiepinglun');
							ui.btnMsgType.classList.remove('icon-yuyin');
							ui.boxMsgText.style.display = 'none';
							ui.boxMsgSound.style.display = 'block';
							ui.boxMsgText.blur();
							document.body.focus();
						} else if (ui.btnMsgType.classList.contains('icon-xiepinglun')) {
							ui.btnMsgType.classList.add('icon-yuyin');
							ui.btnMsgType.classList.remove('icon-xiepinglun');
							ui.boxMsgSound.style.display = 'none';
							ui.boxMsgText.style.display = 'block';
							//--
							//showKeyboard();
							ui.boxMsgText.focus();
							setTimeout(function() {
								ui.boxMsgText.focus();
							}, 150);
						}
					}, false);
					ui.footerLeft.addEventListener('tap', function(event) {
						if(onlineUsers2.hasOwnProperty(code)){ 
							var btnArray = [{
								title: "拍照"
							}, {
								title: "从相册选择"
							}];
							plus.nativeUI.actionSheet({
								title: "选择照片",
								cancel: "取消",
								buttons: btnArray
							}, function(e) {
								var index = e.index;
								switch (index) {
									case 0:
										break;
									case 1:
										var cmr = plus.camera.getCamera();
										cmr.captureImage(function(path) {
											var dstname = "_downloads/" + getUid() + ".jpg";
											compressImage(path, dstname);
											plus.nativeUI.showWaiting( "正在压缩图片" );
											getNewUrl();
	//										send({
	//											sender: 'self',
	//											type: 'image',
	//											content: "file://" + plus.io.convertLocalFileSystemURL(path)
	//										});
										}, function(err) {});
										break;
									case 2:
										plus.gallery.pick(function(path) {
											var dstname = "_downloads/" + getUid() + ".jpg";
											compressImage(path, dstname);
											plus.nativeUI.showWaiting( "正在压缩图片" );
											getNewUrl();
	//										
										}, function(err) {
											
										}, {
											filter: "image"
										});
										break;
								}
							});
						}
						else{
							mui.toast("对方不在线");
						}

						
					}, false); 
					var files = [];
					var newUrlAfterCompress;
					function getNewUrl(){
						if(newUrlAfterCompress!=undefined){
							//console.log("转换后图片:"+newUrlAfterCompress);
							appendFile(newUrlAfterCompress);
							plus.nativeUI.showWaiting( "正在上传图片" );
							upload();
						}
						else{
							setTimeout(getNewUrl,300);
						}
					}
					// 上传文件
					function upload() {
						//var wt = plus.nativeUI.showWaiting();
						var task = plus.uploader.createUpload(server + "?action=testupload", {
								method: "POST"
							},
							function(t, status) { //上传完成
								if (status == 200) {
									//mui.toast("图片上传成功");
									var imgurl=t.responseText; 
									var userimg=plus.storage.getItem("userimg");
									if(userimg.length>3){
										
									}
									else{
										userimg="img/logo.png";
									}
//									console.log(imgurl); 
									var obj = { 
						                send: plus.storage.getItem("loginname"),//this.userid, 
						                username: plus.storage.getItem("loginname"),//this.username, 
						                content: imgurl,
						                contentType:'image',
						                receive:code,
						                groupid:'0',
						                uname:plus.storage.getItem("realname"),
						                upic:userimg,
						                type:'self'
						            };
						            //plus.webview.currentWebview().groupid
						            files = [];
						            newUrlAfterCompress=undefined;
						            this.socket = io.connect('ws://121.40.205.128:3000');
						            this.socket.emit('message', obj);
						            
						            plus.nativeUI.closeWaiting();
									//wt.close();
								} else {
									console.log("上传失败:" + status);

								}
							}
						);
						for (var i = 0; i < files.length; i++) {
							var f = files[i];
//							console.log("准备上传的图片路径:"+f.path);
							task.addFile(f.path, {
								key: f.name
							});
						}
						task.start();
					}
					function appendFile(p) {
						files.push({
							name: "uploadkey",//服务端接收<span style="font-family: Arial, Helvetica, sans-serif;">uploadkey,再转存为图片就行了</span>
							path: p
						});
					}
					// 产生一个随机数
					function getUid() {
						return Math.floor(Math.random() * 100000000 + 10000000).toString();
					}
					//压缩图片
					function compressImage(src, dstname) {
						//var dstname="_downloads/"+getUid()+".jpg";
						plus.zip.compressImage({
								src: src,
								dst: dstname,
								overwrite: true,
								quality: 20//图片压缩
							},
							function(event) {
								//console.log("Compress success:"+event.target);
								newUrlAfterCompress=event.target;
								return event.target;
							},
							function(error) {
								console.log(error);
								return src;
								//alert("Compress error!");
							});
					}
					var setSoundAlertVisable=function(show){
						if(show){
							ui.boxSoundAlert.style.display = 'block';
							ui.boxSoundAlert.style.opacity = 1;
						}else{
							ui.boxSoundAlert.style.opacity = 0;
							//fadeOut 完成再真正隐藏
							setTimeout(function(){
								ui.boxSoundAlert.style.display = 'none';
							},200);
						}
					};
					var recordCancel = false;
					var recorder = null;
					var audio_tips = document.getElementById("audio_tips");
					var startTimestamp = null;
					var stopTimestamp = null;
					var stopTimer = null;
					ui.boxMsgSound.addEventListener('hold', function(event) {
						recordCancel = false;
						if(stopTimer)clearTimeout(stopTimer);
						audio_tips.innerHTML = "手指上划,取消发送";
						ui.boxSoundAlert.classList.remove('rprogress-sigh');
						setSoundAlertVisable(true);
						recorder = plus.audio.getRecorder();
						if (recorder == null) {
							plus.nativeUI.toast("不能获取录音对象");
							return;
						}
						startTimestamp = (new Date()).getTime();
						recorder.record({
							filename: "_doc/audio/"
						}, function(path) {
							if (recordCancel) return;
							send({
								sender: 'self',
								type: 'sound',
								content: path
							});
						}, function(e) {
							plus.nativeUI.toast("录音时出现异常: " + e.message);
						});
					}, false);
					ui.body.addEventListener('drag', function(event) {
						//console.log('drag');
						if (Math.abs(event.detail.deltaY) > 50) {
							if (!recordCancel) {
								recordCancel = true;
								if (!audio_tips.classList.contains("cancel")) {
									audio_tips.classList.add("cancel");
								}
								audio_tips.innerHTML = "松开手指,取消发送";
							}
						} else {
							if (recordCancel) {
								recordCancel = false;
								if (audio_tips.classList.contains("cancel")) {
									audio_tips.classList.remove("cancel");
								}
								audio_tips.innerHTML = "手指上划,取消发送";
							}
						}
					}, false);
					ui.boxMsgSound.addEventListener('release', function(event) {
						//console.log('release');
						if (audio_tips.classList.contains("cancel")) {
							audio_tips.classList.remove("cancel");
							audio_tips.innerHTML = "手指上划,取消发送";
						}
						//
						stopTimestamp = (new Date()).getTime();
						if (stopTimestamp - startTimestamp < MIN_SOUND_TIME) {
							audio_tips.innerHTML = "录音时间太短";
							ui.boxSoundAlert.classList.add('rprogress-sigh');
							recordCancel = true;
							stopTimer=setTimeout(function(){
								setSoundAlertVisable(false);
							},800);
						}else{
							setSoundAlertVisable(false);
						}
						recorder.stop();
					}, false);
					ui.boxMsgSound.addEventListener("touchstart", function(e) {
						//console.log("start....");
						e.preventDefault();
					});
					ui.boxMsgText.addEventListener('input', function(event) {
						ui.btnMsgType.classList['add']('mui-icon-paperplane');
						ui.btnMsgType.setAttribute("for", ui.boxMsgText.value == '' ? '' : 'msg-text');
						ui.h.innerText = ui.boxMsgText.value.replace(new RegExp('\n', 'gm'), '\n-') || '-';
						ui.footer.style.height = (ui.h.offsetHeight + footerPadding) + 'px';
						ui.content.style.paddingBottom = ui.footer.style.height;
					});
					ui.boxMsgText.addEventListener('tap', function(event) {
						ui.boxMsgText.focus();
						setTimeout(function() {
							ui.boxMsgText.focus();
						}, 0);
					}, false);
				var conn=new DBConn();
				//保存联系人表
				function insertData(send,receive,content,uname){
					var sql="select * from chart_list where send='"+send+"' and receive='"+receive+"'";
					console.log("监听最近联系人"+sql);
					conn.executeScarl(sql,
						function(tx,result){
							console.log("sql的结果集"+result.rows.length);
							if(result.rows.length>0){
								//存在最近记录
								sql="update chart_list set content='"+content+"' where send='"+send+"' and receive='"+receive+"'";
								conn.executeSqlDefault(sql,
									[],
									function (tx, result) {
										//保存成功
									},
									function (tx, error) {
										console.log('记录保存失败: ' + error.message);
										
									}
								);
							}else{
								conn.executeScarl("select * from chart_list order by id desc limit 0,1",
									function(tx,result){
										/*var id=0;
										if(result.rows.length>0){
											id=parseInt(result.rows.item(0)["id"])+1;
										}else{
											id=1;
										}*/
										//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
										var da=new Date();
										var adddate=da.getFullYear()+"-"+(da.getMonth()+1)+"-"+da.getDay()+" "+da.getHours()+":"+da.getMinutes()+":"+da.getSeconds();
										sql="insert into chart_list (send,receive,addtime,content,groupid,uname) values('"+send+"','"+receive+"','"+adddate+"','"+content+"',0,'"+uname+"')";
										//console.log(sql);   
										conn.executeSqlDefault(sql,
											[],
											function (tx, result) {
												//保存成功
											},
											function (tx, error) {
												console.log('记录保存失败: ' + error.message); 
											}
										);
									}
								)
							}
						},function(tx,error){
							console.log(error);
						}
					);
				}
				//保存聊天内容表
				function insertDataContent(id,send,receive,adddate,content,contentType,type,upic){
					conn.executeScarl("select * from chart_list_content order by addtime desc limit 0,1",
						function(tx,result){
							var type="";
							if(plus.storage.getItem("loginname")==send){
								type='self';
							}else{
								type='send';
							}
							//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
							var sql="insert into chart_list_content (id,send,receive,addtime,content,contentType,type,isread,upic) values('"+id+"','"+send+"','"+receive+"','"+adddate+"','"+content+"','"+contentType+"','"+type+"',1,'"+upic+"')";
//							console.log(sql);
							//console.log(sql+"ee");
							conn.executeSqlDefault(sql,
								[],
								function (tx, result) {
									//保存成功
									record.push({
										sender: type,
										type: contentType,
										content: content,
										addtime:adddate,
										upic:upic
									});
									bindMsgList();
								},
								function (tx, error) {
									console.log('记录保存失败: ' + error.message); 
								}
							);
						}
					)
				}
				//群组--------------------------
				//保存联系人表
				function insertGroupData(send,receive,content,groupid,gname,pic){
					var sql="";
					conn.executeScarl("select * from chart_list where groupid='"+groupid+"'",
						function(tx,result){
							if(result.rows.length>0){
								//存在最近记录
								sql="update chart_list set content='"+content+"' where groupid='"+groupid+"'";
								conn.executeSqlDefault(sql,
									[],
									function (tx, result) {
										//保存成功
									},
									function (tx, error) {
										console.log('记录保存失败: ' + error.message); 
									}
								);
							}else{
								conn.executeScarl("select * from chart_list order by addtime desc limit 0,1",
									function(tx,result){
										/*var id=0;
										if(result.rows.length>0){
											id=parseInt(result.rows.item(0)["id"])+1;
										}else{
											id=1;
										}*/
										//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
										var da=new Date();
										var adddate=da.getFullYear()+"-"+(da.getMonth()+1)+"-"+da.getDay()+" "+da.getHours()+":"+da.getMinutes()+":"+da.getSeconds();
										sql="insert into chart_list (send,receive,addtime,content,groupid,uname,gname,pic) values('','','"+adddate+"','"+content+"','"+groupid+"','','"+gname+"','"+pic+"')";
//										console.log(sql);
										conn.executeSqlDefault(sql,
											[],
											function (tx, result) {
												//保存成功
											},
											function (tx, error) {
												console.log('记录保存失败: ' + error.message); 
											}
										);
									}
								)
							}
						}
					);
				}
				//保存群组聊天内容表
				function insertDataGroupContent(id,send,receive,adddate,content,contentType,type,groupid){
					conn.executeScarl("select * from chart_group_list_content order by addtime desc limit 0,1",
						function(tx,result){
							var type="";
							if(plus.storage.getItem("loginname")==send){
								type='self';
							}else{
								type='send';
							}
							//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
							var sql="insert into chart_group_list_content (id,send,content,contentType,addtime,type,groupid) values('"+id+"','"+send+"','"+content+"','"+contentType+"','"+adddate+"','"+type+"',"+groupid+")";
							//console.log(sql);
							conn.executeSqlDefault(sql,
								[],
								function (tx, result) {
									//保存成功
									//initList();
								},
								function (tx, error) {
									console.log('记录保存失败: ' + error.message); 
								}
							);
						}
					)
				}
				
				//显示本地聊天信息
				function initData(){
					//conn.executeScarl("select * from chart_list_content where (send='"+plus.webview.currentWebview().account+"' or send='"+plus.storage.getItem("loginname")+"') and (receive='"+plus.storage.getItem("loginname")+"' or receive='"+plus.webview.currentWebview().account+"')  order by id asc limit 0,100",  
					conn.executeScarl("select * from chart_list_content where (send='"+plus.webview.currentWebview().account+"' and receive='"+plus.storage.getItem("loginname")+"') or (send='"+plus.storage.getItem("loginname")+"' and receive='"+plus.webview.currentWebview().account+"')  order by id asc limit 0,100",
					function(tx,result){
						if(result.rows.length>0){
							for(var i=0;i<result.rows.length;i++){
								record.push({
									sender: result.rows.item(i)["type"],
									type: result.rows.item(i)["contentType"],
									content: result.rows.item(i)["content"],
									addtime:result.rows.item(i)["addtime"],
									groupid:0,
									upic:result.rows.item(i)["upic"]
								});
								bindMsgList();
							}
						}
					});
				};
				initData();
				
					
				var d = document,
				w = window, 
				p = parseInt, 
				dd = d.documentElement, 
				db = d.body, 
				dc = d.compatMode == 'CSS1Compat', 
				dx = dc ? dd: db, 
				ec = encodeURIComponent;
				
				w.CHAT = { 
				    msgObj:d.getElementById("message"), 
				    screenheight:w.innerHeight ? w.innerHeight : dx.clientHeight, 
				    username:null,
				    userid:null,
				    socket:null,
				    onlineUsers:null,
				    reivice:null,
				    //让浏览器滚动条保持在最低部 
				    scrollToBottom:function(){ 
				        //w.scrollTo(0, this.msgObj.clientHeight); 
				    },
				    //退出,本例只是一个简单的刷新 
				    logout:function(){ 
				        //this.socket.disconnect(); 
				        //location.reload(); 
				    }, 
				    //提交聊天消息内容 
				    submit:function(content,reivicer){
				        var content = content;
				        if(content != ''){ 
				        	var arrUserList;
//				        	var arrUserList=onlineUsers.split('、');
							if(onlineUsers2.hasOwnProperty(reivicer)){ 
				                var userimg=plus.storage.getItem("userimg");
				        	
					        	if(userimg.length<1){
					        		userimg="img/logo.png";
					        	}
					            var obj = { 
					                send: plus.storage.getItem("loginname"),//this.userid, 
					                username: plus.storage.getItem("loginname"),//this.username, 
					                content: content,
					                contentType:'text',
					                receive:reivicer,
					                groupid:0,
					                type:'self',
					                uname:plus.storage.getItem("realname"),
					                upic:userimg
					            };
					            this.socket = io.connect('ws://121.40.205.128:3000');
					            this.socket.emit('message', obj);
				            } 
				            else{
				            	mui.toast("对方不在线");
				            	return false;
				            }
//				        	console.log(arrUserList);
				        	
				        }
				        
				        return false; 
				    }, 
				    genUid:function(){ 
				        return new Date().getTime()+""+Math.floor(Math.random()*899+100); 
				    }, 
				    //更新系统消息,本例中在用户加入、退出的时候调用 
				    updateSysMsg:function(o, action){ 
				        //当前在线用户列表 
				        onlineUsers2 = o.onlineUsers; 
				        //当前在线人数 
				        var onlineCount = o.onlineCount; 
				        //新加入用户的信息 
				        var user = o.user; 
				            
				        //更新在线人数 
				        var userhtml = ''; 
				        var separator = ''; 
//				        for(key in onlineUsers) { 
//				            if(onlineUsers2.hasOwnProperty(key)){ 
//				                userhtml += separator+onlineUsers[key]; 
//				                separator = '、'; 
//				            } 
//				        } 
				    }, 
				    //第一个界面用户提交用户名 
				    usernameSubmit:function(){
				        return false; 
				    },
				    init:function(){
				        /* 
				        客户端根据时间和随机数生成uid,这样使得聊天室用户名称可以重复。 
				        实际项目中,如果是需要用户登录,那么直接采用用户的uid来做标识就可以 
				        */
				        this.userid = plus.storage.getItem("loginname"); 
				        this.username = plus.storage.getItem("loginname"); 
				        
				        //连接websocket后端服务器 
				        this.socket = io.connect('ws://121.40.205.128:3000');
				        
				        //告诉服务器端有用户登录 
				        this.socket.emit('login', {userid:this.userid, username:this.username}); 
				        
				        //监听新用户登录 
				        this.socket.on('login', function(o){ 
				            CHAT.updateSysMsg(o, 'login');  
				        }); 
				        
				        //监听用户退出 
				        this.socket.on('logout', function(o){ 
				            CHAT.updateSysMsg(o, 'logout'); 
				        });
				        //监听消息发送 
				        this.socket.on('message', function(obj){
				        	//监听服务器发送的消息,保存到本地,然后展示
//				        	console.log("监听时收到的obj.groupid"+obj.groupid);
				        	if(obj.groupid==0){
					        	conn.executeScarl("select * from chart_list_content where id='"+obj.id+"'",  
								function(tx,result){
					        		//单人聊天监听保存
					        		conn.executeScarl("select * from chart_list_content where id='"+obj.id+"'",  
									function(tx,result){
										if(result.rows.length==0){
											var send="";
											if(obj.send==plus.storage.getItem("loginname")){
												send=obj.receive;
											}else{
												send=obj.send;
											}
											//insertData(send,receive,content,uname)
											insertData(send,plus.storage.getItem("loginname"),obj.content,obj.uname);
						        			insertDataContent(obj.id,obj.send,obj.receive,obj.addtime,obj.content,obj.contentType,obj.type,obj.upic);
										}
									});
					        	
								});
							}else{
				        		//群组聊天监听保存
				        		conn.executeScarl("select * from chart_group_list_content where id='"+obj.id+"'",  
								function(tx,result){
									if(result.rows.length==0){
										var send="";
										if(obj.send==plus.storage.getItem("loginname")){
											send=obj.receive;
										}else{
											send=obj.send;
										}
										if(localStorage.chartitem!="show"){
											
										}else{
											//initList();
											//insertGroupData(send,receive,content,groupid,gname,pic){
											insertGroupData(send,plus.storage.getItem("loginname"),obj.content,obj.groupid,"",plus.storage.getItem("userimg"));
				        					insertDataGroupContent(obj.id,obj.send,obj.receive,obj.addtime,obj.content,obj.contentType,obj.type,1);
										}
									}
								});
				        	}
			            });
			            this.socket.on('notline', function(obj){
			            	mui.toast("对方不在线");
			            });
			        } 
			    };
				CHAT.init();
			});
			}(mui, document));
		</script>
	</body>
</html>

服务端接收图片,并返回网络路径:

int l = Request.Files["uploadkey"].ContentLength;
byte[] buffer = new byte[l];
Stream s = Request.Files["uploadkey"].InputStream;
//string imgtype = Request.Files[3 + i].ContentType;
//image/png
System.Drawing.Bitmap image = new System.Drawing.Bitmap(s);
string imgname = Common.GetGuid() + ".jpg";
string path = "Images/" + DateTime.Now.ToString("yyyyMMdd");
if (!Directory.Exists(HttpContext.Current.Server.MapPath(path)))
{
    System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(path));
}
string newurl=Server.MapPath(path + "/" + imgname);
image.Save(newurl);








以上是关于H5+MUI+Node.js+Socket.io实现即时聊天以及发送+图片压缩的主要内容,如果未能解决你的问题,请参考以下文章

未找到 Socket.io.js(node.js + express + socket.io)

Node.js - Socket.io:socket.request 未定义

HTTP 状态代码 200 但页面未加载 Node.js Socket.io -- 使用 Socket.io 的 Node.js 教程,Daniel Nill,fs.readFile(),socket

Node.js 和 socket.io 的混淆

Node.js socket.io.js 未找到或 io 未定义

找不到Node.js /socket.io/socket.io.js express 4.0