H5页面上传图片控件

做H5项目的时候应该经常会遇到上传图片的问题的,在这里介绍一种目前项目里面用到的一个H5页面上传图片的控件,代码如下:

html代码:

<!doctype html>
<#include "/ftl/common/base.ftl">
<html>
<head>
<meta charset="utf-8">
<title>::去家玩::</title>
<meta name="viewport" content="user-scalable=0, width=device-width, initial-scale=1.0,  minimum-scale=1.0, maximum-scale=1.0">
<meta content="telephone=no" name="format-detection" />
<meta content="black" name="apple-mobile-web-app-status-bar-style" />
<link rel="stylesheet" type="text/css" href="${URLPrefix.statics}/css/reset.css" />
<link rel="stylesheet" type="text/css" href="${URLPrefix.statics}/css/common.css" />
<link rel="stylesheet" type="text/css" href="${URLPrefix.statics}/css/oldPopBox.css" />
<link rel="stylesheet" type="text/css" href="${URLPrefix.statics}/css/showPhoto.css" />
<script type='text/javascript' src="${URLPrefix.statics}/js/jquery.js"></script>
<script type='text/javascript' src="${URLPrefix.statics}/js/browser.js"></script>
<script type='text/javascript' src="${URLPrefix.statics}/js/imgCompressUpload.js"></script>
</head>

<body id="bodyBox">
	
	<!--@header-->
    <header class="header">
        <h2>秀萌照</h2>
	    <a class="back" href="${URLPrefix.statics}/toGrowIndex.do?childId=${(childId?c)!''}"  rel="nofollow"><em class="icon30" data-icon=""></em></a>
    </header>
	<!--}}header-->


	<div class="popShowPhoto">
		<em class="icon icon-close icon30" data-icon=""></em>
        <img src="../../images/liuzhukuaile.png" alt="">
        <div class="growthNav tEqual tEqual_nobor">
        		<div class="tEtd">
					<a class="onclickShow" οnclick="return $(this).next().click();" class="upLoadImg" id="cameraStart"><em class="icon icon-zhaoxiangji" data-icon=""></em><span class="blk">拍照</span></a><input type="file" id="choose" style="display:none" accept="image/*" multiple>
				</div>	       	
				<div class="tEtd">
					<a class="onclickShow" οnclick="return $(this).next().click();" class="upLoadImg" id="albumStart"><em class="icon icon-xiangce" data-icon=""></em><span class="blk">相册</span></a><input type="file" id="choose" style="display:none" accept="image/*" multiple>
				</div>	
				<div class="tEtd">
					<a class="onclickShow"><em class="icon icon-wenzi" data-icon=""></em><span class="blk">文字</span></a>
				</div>					
			</div>
	</div>
	

     <!--@main-->
    <div id="main" class="main main_t">
                
			<form action="#" method="post" id="showFm" >
            <section class="Hbox auto">
        		<div class="measureH">
                    <div class="layout nopad">	
                        <ul class="logFm taH">
                            <li class="hm nobor">
                                <textarea class="textarea" cols=""  name="comment" id="comment"  rows="5" placeholder="给宝宝说点什么吧~"></textarea>
                                <span class="Vmsg" data-for="comment" data-rule="required"  data-pass=" " data-passhide="1" data-warn="内容不能为空"> </span>
                                <span class="Vmsg" data-for="comment" data-rule="range" data-range="0,140" data-pass=" " data-passhide="1" data-warn="字数超过140"> </span>
                            </li>
                        </ul>
                        <div class="upLoad">
			                <ul>
			                    <li><div οnclick="return $(this).next().click();" class="upLoadImg" id="upload">+</div><input type="file" id="choose" style="display:none" accept="image/*" multiple></li>
			                </ul>
			            </div>
                        <input type="hidden" name="childId" id="childId" value="${(childId?c)!''}">
                        <input type="hidden" name="pictureUrl" id="pictureUrl">  
                    </div>
                </div>
            </section>
			
        
    </div>
    		<div style="padding:2rem 1rem 0rem 1rem;">   		
				<ul class="logFm">
					<li class="sbmt">
						<button class="ibtn oran" type="button"  id="subBtn">发 表</button>
					</li>	
				</ul>
			</div>
    </form>
    <!--}}main-->
    <!--}}main-->
    <script type='text/javascript' src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>	
    <script src="${URLPrefix.statics}/js/require.js" data-main="${URLPrefix.statics}/js/config"></script>
     <script type="text/javascript">
	      require(['core_mobi','zui_mobi','common'], function (){
	      
	      var userToken=$.cookie.get('ut');
	      
	        //文本点击事件
			$('#showPj').on('click',function(e){
				e.preventDefault();
				var a = $(this);
				if("给宝宝说点什么吧!"==$('#showPj').val()){
				   $('#showPj').val("");
				}
			});
			
		
		//关闭秀萌照弹层
		$("body").on("click",".icon-close,.onclickShow",function(){
			$(".popShowPhoto").fadeOut(1000);
		});		
			
			if ($.browser.mobile) {//判断是否是移动设备打开。browser代码在下面
               		var ua = navigator.userAgent.toLowerCase();//获取判断用的对象
			        if (ua.match(/MicroMessenger/i) == "micromessenger") {
			                //在微信中打开
			                $(function(){
									$.ajax({
								            headers: {userToken:userToken},
											type: "POST",
											dataType: "json",
											data:{
											        url:location.href
											      },
											url: "service/weixin/getSignature"//获取签名
										}).done(function(response) {
										    data = response.data;
										    wx.config({
											    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
											    appId: data.appid, // 必填,公众号的唯一标识
											    timestamp:data.timestamp, // 必填,生成签名的时间戳
											    nonceStr: data.nonceStr, // 必填,生成签名的随机串
											    signature: data.signature,// 必填,签名,见附录1
											   jsApiList: ['chooseImage','getLocation','previewImage','uploadImage','downloadImage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
											});
											wx.ready(function(){
											    $('#addPic').on('click',function(){
											         var uploadBtn=$(this);
												      wx.chooseImage({
														    count: 9, // 默认9
														    sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
														    sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
														    success: function (res) {
														        var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
														         var pics='';
														         var i=0;
														         var length=res.localIds.length;
											                            var upload = function(){
											                                  var imageId=res.localIds[i];
											                                  wx.uploadImage({
																				    localId: imageId, // 需要上传的图片的本地ID,由chooseImage接口获得
																				    isShowProgressTips: 1, // 默认为1,显示进度提示
																				    success: function (res) {
																				        var serverId = res.serverId; // 返回图片的服务器端ID
																				        var uploadUrl="${URLPrefix.statics}/service/weixin/upload";
																				        var uploadType=1;// 0:游戏;1:成长;2:头像;3:其他
																				        uploadAliyunImage(uploadUrl,serverId,uploadType,"pictureUrl",true);
																				        pics = '<span class="showPic"><img src="'+imageId+'" id="headPicture'+i+'"/></span>';
																				        i++;//如果还有照片,继续上传
																				        uploadBtn.before(pics);
																				        if(i<length){
																				            upload();
																				        }
																				    }
																			  });
											                            }
											                            upload();
														    }
														});
												});
											});
										});
										wx.error(function(res){
										    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
										});
										
						});
			                
			        }
			        if ($.browser.ios) {
			                //是否在IOS浏览器打开
			               // alert("请在微信内打开");
			        } 
			        if($.browser.android){
			                //是否在安卓浏览器打开
			               //  alert("请在微信内打开");
			        }
			} else {
			        //否则就是PC浏览器打开
			       //  alert("请在微信内打开");
			       $("#cameraStart").hide();
			}

				//点击发表
				var arBusy = false;
				var valid = new ZUI.Validator("showFm",{
				ruleTag:'span.Vmsg',
				tagClass:'Vmsg',
				valiHide:true,
				autoSbmit:false,
				submitBtn:'#subBtn',
				onSubmit: function(fm,err){
					if(err<1){//评论验证通过
					var url = "${URLPrefix.statics}/service/growShowPhotos/addShowPhotos";
					$.ajax({
					    headers: {userToken:$.cookie.get('ut')},
						type: "POST",
						dataType: "json",
						url: url,//注意地址
						data:$('#showFm').serialize()// formid
					}).done(function(response) {
						myBox.alert(response.msg,{
							boxtitle:'去家玩',
							auto:true,
							onShow:function(){
								if(response.code=="0"){
								    window.location.href = "${URLPrefix.statics}/toGrowIndex.do?childId=${childId}";//userToken失效跳转登录页面
								};
							}
						});
						});
					}else{
						Infos.info($('.Verro').eq(0).data('warn'), {'hideAfter': 5000});
					}
				}
			}),actBusy = false;//游戏报名
			
		
	      });
	      
      	/*删除照片*/
      	$("body").on("click",".delete",function(){
			$(this).parent(".pic").remove();
			$("#pictureUrl").val($("#pictureUrl").val().replace($(this).prev().attr("src") + ",", ""));
      	});
      	
	    //上传回调方法
      	function callbackUpload(filePath){
      		$(".upLoadImg").before('<div class="pic"><img src="'+filePath+'" alt="" /><em class="icon20 delete" data-icon=""></em></div>');
          	$(".delete").show();
          	$("#pictureUrl").val($("#pictureUrl").val() + filePath + ",");
      	}
      </script>
</body>
</html>
 那段判断是否在手机里面打开的代码作用是在pc端打开的话会隐藏掉拍照功能,因为pc端不好调用摄像头,而head标签引入的那段imgCompressUpload.js就是上传图片的控件,html代码里面用到了许多接口的url,直接复制代码是看不到任何效果的,这里只是想把元素都展现出来,方便控件里面对相应元素进行操作。

控件js代码如下:

$(function(){
  var filechooser = document.getElementById("choose");

  //    用于压缩图片的canvas
  var canvas = document.createElement("canvas");
  var ctx = canvas.getContext('2d');

  //    瓦片canvas
  var tCanvas = document.createElement("canvas");
  var tctx = tCanvas.getContext("2d");

  var maxsize = 100 * 1024;

  // ios设备需要调两次才有效果,所以在点击的控件上添加一次调用,在此处在绑定一次,其他设备一次即可
  if(browser.versions.ios){
	  $("#upload,#cameraStart,#albumStart").on("click", function() {
        return filechooser.click();
      })
      .on("touchstart", function() {
        $(this).addClass("touch")
      })
      .on("touchend", function() {
        $(this).removeClass("touch")
      });
  }

  filechooser.onchange = function() {
    if (!this.files.length) return;

    var files = Array.prototype.slice.call(this.files);

    if (files.length > 4) {
      alert("最多同时只可上传4张图片");
      return;
    }

    files.forEach(function(file, i) {
      if (!/\/(?:jpeg|png|gif|bmp)/i.test(file.type)) return;

      var reader = new FileReader();

      var li = document.createElement("li");

//          获取图片大小
      var size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "MB" : ~~(file.size / 1024) + "KB";

      reader.onload = function() {
        var result = this.result;
        var img = new Image();
        img.src = result;

        $(li).css("background-image", "url(" + result + ")");

        //如果图片大小小于100kb,则直接上传
        if (result.length <= maxsize) {
          img = null;

          upload(result, file.type, $(li));

          return;
        }

//      图片加载完毕之后进行压缩,然后上传
        if (img.complete) {
          callback();
        } else {
          img.onload = callback;
        }

        function callback() {
          var data = compress(img);

          upload(data, file.type, $(li));

          img = null;
        }

      };

      reader.readAsDataURL(file);
    })
  };

  //    使用canvas对大图片进行压缩
  function compress(img) {
    var initSize = img.src.length;
    var width = img.width;
    var height = img.height;

    //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
    var ratio;
    if ((ratio = width * height / 4000000) > 1) {
      ratio = Math.sqrt(ratio);
      width /= ratio;
      height /= ratio;
    } else {
      ratio = 1;
    }

    canvas.width = width;
    canvas.height = height;

//        铺底色
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    //如果图片像素大于100万则使用瓦片绘制
    var count;
    if ((count = width * height / 1000000) > 1) {
      count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片

//            计算每块瓦片的宽和高
      var nw = ~~(width / count);
      var nh = ~~(height / count);

      tCanvas.width = nw;
      tCanvas.height = nh;

      for (var i = 0; i < count; i++) {
        for (var j = 0; j < count; j++) {
          tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);

          ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
        }
      }
    } else {
      ctx.drawImage(img, 0, 0, width, height);
    }

    //进行最小压缩
    var ndata = canvas.toDataURL('image/jpeg', 0.1);

    console.log('压缩前:' + initSize);
    console.log('压缩后:' + ndata.length);
    console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");

    tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;

    return ndata;
  }

  //    图片上传,将base64的图片转成二进制对象,塞进formdata上传
  function upload(basestr, type, $li) {
    var text = window.atob(basestr.split(",")[1]);
    var buffer = new Uint8Array(text.length);
    var pecent = 0, loop = null;

    for (var i = 0; i < text.length; i++) {
      buffer[i] = text.charCodeAt(i);
    }

    var blob = getBlob([buffer], type);

    var xhr = new XMLHttpRequest();

    var formdata = getFormData();

    formdata.append('imagefile', blob);

    //上传压缩图片至阿里云服务器
    xhr.open('post', '/imgUpload/upload.do?fileType=' + type);
    
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4 && xhr.status == 200) {
        var jsonData = JSON.parse(xhr.responseText);
        var text = jsonData.path ? '上传成功' : '上传失败';

        console.log(text + ':' + jsonData.path);
        
        //回调页面方法
        callbackUpload(jsonData.path);

      }
    };

    xhr.send(formdata);
  }

  /**
   * 获取blob对象的兼容性写法
   * @param buffer
   * @param format
   * @returns {*}
   */
  function getBlob(buffer, format) {
    try {
      return new Blob(buffer, {type: format});
    } catch (e) {
      var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder);
      buffer.forEach(function(buf) {
        bb.append(buf);
      });
      return bb.getBlob(format);
    }
  }

  /**
   * 获取formdata
   */
  function getFormData() {
    var isNeedShim = ~navigator.userAgent.indexOf('Android')
        && ~navigator.vendor.indexOf('Google')
        && !~navigator.userAgent.indexOf('Chrome')
        && navigator.userAgent.match(/AppleWebKit\/(\d+)/).pop() <= 534;

    return isNeedShim ? new FormDataShim() : new FormData()
  }

  /**
   * formdata 补丁, 给不支持formdata上传blob的android机打补丁
   * @constructor
   */
  function FormDataShim() {
    console.warn('using formdata shim');

    var o = this,
        parts = [],
        boundary = Array(21).join('-') + (+new Date() * (1e16 * Math.random())).toString(36),
        oldSend = XMLHttpRequest.prototype.send;

    this.append = function(name, value, filename) {
      parts.push('--' + boundary + '\r\nContent-Disposition: form-data; name="' + name + '"');

      if (value instanceof Blob) {
        parts.push('; filename="' + (filename || 'blob') + '"\r\nContent-Type: ' + value.type + '\r\n\r\n');
        parts.push(value);
      }
      else {
        parts.push('\r\n\r\n' + value);
      }
      parts.push('\r\n');
    };

    // Override XHR send()
    XMLHttpRequest.prototype.send = function(val) {
      var fr,
          data,
          oXHR = this;

      if (val === o) {
        // Append the final boundary string
        parts.push('--' + boundary + '--\r\n');

        // Create the blob
        data = getBlob(parts);

        // Set up and read the blob into an array to be sent
        fr = new FileReader();
        fr.onload = function() {
          oldSend.call(oXHR, fr.result);
        };
        fr.onerror = function(err) {
          throw err;
        };
        fr.readAsArrayBuffer(data);

        // Set the multipart content type and boudary
        this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
        XMLHttpRequest.prototype.send = oldSend;
      }
      else {
        oldSend.call(this, val);
      }
    };
  }
});
对元素进行的操作就是在点击页面中id为 upload,cameraStart,albumStart时候return filechooser.click()方法,而html页面里面在id为upload,cameraStart,albumStart元素后面都会有<input type="file" id="choose" style="display:none" accept="image/*" multiple>,这里的input type="file"加上控件和页面里面相应js的控制即可实现图片上传,之所以写的不清楚也是因为第一次接触到这个方面,深层次的原理也有待日后的学习与理解,先上传博客咯。

 


  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值