您的位置:首页 > Web前端 > HTML5

H5页面上传图片控件

2016-08-05 17:20 393 查看
做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" onclick="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" onclick="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 onclick="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的控制即可实现图片上传,之所以写的不清楚也是因为第一次接触到这个方面,深层次的原理也有待日后的学习与理解,先上传博客咯。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: