jQuery仿QQ Ajax上传文件+Jcrop照片剪裁插件,如果浏览器支持html5,会有一个上传进度条。
本文只提供前端代码,图片处理代码,自行百度。
第一步、页面引入必要的css和js(文件在本文最后,提供下载地址,供学习使用):
<link rel="stylesheet" type="text/css" href="css/open_platform.css" />
<link rel="stylesheet" type="text/css" href="css/open_qq_agreement.css" />
<link rel="stylesheet" type="text/css" href="css/confirm_by_dialog.css" />
<link rel="stylesheet" type="text/css" href="css/smoothness/jquery-ui-1.9.0.custom.min.css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.9.0.custom.min.js"></script>
<script type="text/javascript" src="js/qzfl_for_qzone.js"></script>
<script type="text/javascript" src="js/open_v2.js"></script>
<script type="text/javascript" src="js/fileupload.js"></script>
第二步、写html代码,一个上传按钮和一个预览图
<div class="div_btn img_upload_panel">
<input type="hidden" name="face_path" value="" />
<p class="pic" >
<img src="image/default_100.jpg" id="icon_img" />
</p>
<div class="clear"></div>
<br />
<p><input type="button" value="上传图片" class="file_icon_upload_btn"/></p>
<br />
</div>
第三步、给上传按钮绑定上传事件
<script type="text/javascript" >
$(document).ready(function(){
//图标上传
$(".file_icon_upload_btn").click(function(){
var post_url ="uploadify.json?type=icon",
desc="选择一个255x255,大小1MB以内,png/jpg 格式的图片",
pf_id=1,_flag="255_255",_size=1024*1024;
var _this=$(this);
OP_COMMON.upload.showUpload(post_url,
function(ret) {
//上传回调函数//
$("#icon_img").attr("src",ret.filePath);
$(_this).val("更改");
},
desc, _size, false,_flag, {
customContent: '<input type="hidden" name="pf" value="' + pf_id + '" />'
});
});
});
</script>
示例截图
文件上传核心js
fileupload.js
OP_COMMON = {
url: {
default_img: ""
},
dialog_msg: function(msg) {
parent.QZFL.dialog.create('提示', '<p style="padding:40px 20px 0; line-height:1.8em;">' + msg + '</p>', {
width: 300,
height: 120,
showMask: true
});
},
OP_TIPS: {
icon_16: {
title: "应用小图标",
info: [{
desc: "16×16应用图标会出现在平台应用列表。以空间为例。平台应用中心的各类应用排行榜:",
img: ""
}]
},
icon_100: {
title: "应用大图标",
left: -50,
info: [{
desc: "100×100应用图标会出现在平台推广类Feeds中,以空间平台为例:",
img: ""
},
{
img: ""
}]
}
},
util: {
reg_exps: {
email: /^[0-9A-Za-z-\_.]+@[0-9A-Za-z-\_]+(.[0-9A-Za-z-\_]+)+$/,
url: /^http(s)*://[w-]+(.[w-]+)+(:d+)?(/[w.%-]+)*/?$/i,
url_parm_hash: /^http(s)*://[w-]+(.[w-]+)+(:d+)?(/[?#/-_.!~*'()w%&=]*$)?/i,
phone: /^([0-9]+-)*[0-9]+$/,
mobile_phone: /^1d{10}$/,
uin: /^[1-9][0-9]{4,9}$/,
common: /^[0-9a-zA-Zu4E00-u9FA5uF900-uFA2D]+$/,
company_idcard: /^[0-9]{10,20}$/,
person_idcard: /^[0-9xX]{18}$/,
passport: /^[0-9a-zA-Z]+$/,
lazy: /^[^<>'"]+$/,
human_name: /^[a-zA-Zu4E00-u9FA5uF900-uFA2D][a-zA-Zu4E00-u9FA5uF900-uFA2Ds]*$/,
human_name_cn_no_nec: /^([u4E00-u9FA5]{2,5}|.{0,0})$/,
sensetive: /^[^'"<>]+$/,
num: /(^[1-9][0-9]*$)|(^0$)/,
num_positive: /^[1-9][0-9]*$/
},
showMask: function(zIndex, win) {
var ind = arguments.callee.ind || 1000,
zIndex = zIndex || 100,
style,
width,
height;
win = win || top;
arguments.callee.ind = ++ind;
width = Math.max(win.QZFL.dom.getClientWidth(), win.QZFL.dom.getScrollWidth());
height = Math.max(win.QZFL.dom.getClientHeight(), win.QZFL.dom.getScrollHeight());
style = 'position:absolute;left:0;top:0;background-color:#000;width:' + width + 'px;height:' + height + 'px;z-index:' + zIndex + ';visibility:hidden;';
var el = win.QZFL.dom.createElementIn("div", win.document.body, false, {
id: "op_mask_" + ind,
style: style,
"class": "op_mask"
});
win.$e(el).setStyle({
"opacity": 0.4,
"visibility": "visible"
});
return ind;
},
hideMask: function(ind, win) {
win = win || top;
win.document.body.removeChild(win.document.getElementById("op_mask_" + ind));
},
validate_tip: function(el, type, msg) {
var $tip = $e('.j_open_validate_tip', el.parentNode.parentNode);
if ("error" == type) {
$tip.addClass("form_panel_msg_advise").setHtml('<b class="form_tips nopass"><i class="ico ico_tips"></i>' + (msg ? msg: '') + '</b>').setStyle("display", "block");
} else if ("succ" == type) {
$tip.removeClass("form_panel_msg_advise").setHtml('<b class="form_tips pass"><i class="ico ico_tips"></i>' + (msg ? msg: '') + '</b>').setStyle("display", "block");
} else {
$tip.removeClass("form_panel_msg_advise").setHtml('<i class="ico ico_tips"></i>' + (msg ? msg: '')).setStyle("display", "block");
}
},
water_mark: {
show: function(el, msg) {
if (!QZFL.string.trim(el.value)) {
el.value = msg || el.getAttribute("water_mark");
el.style.color = "#999";
el._ever_focused = false;
} else {
el._ever_focused = true;
}
},
hide: function(el) {
el.value = "";
el.style.color = "#000";
}
},
set_value: function(el, val) {
el.value = val;
el.style.color = "#000";
el._ever_focused = true;
},
form_validate: function(fn_suc) {
var _this = this;
var _validate = function(onblur) {
var input = this,
val = this.value;
val = val.replace(/s+$/, "");
if (! (_this.reg_exps[this.getAttribute("validate")] && _this.reg_exps[this.getAttribute("validate")].test(val))) {
if (0 == QZFL.string.trim(val).length) {
if (onblur) {
_this.water_mark.show(this);
} else {
_this.validate_tip(this, "error", "该项不能为空");
}
} else {
_this.validate_tip(this, "error", this.getAttribute("validate_tip"));
}
return false;
} else {
if ("function" == typeof fn_suc) {
if (false === fn_suc(_this, input, onblur)) {
return false;
}
} else {
_this.validate_tip(this, "succ");
}
return true;
}
};
QZFL.each(document.forms,
function(f) {
f._validate = function() {
var ret = true;
$e('[validate]', this).each(function() {
if (!this._ever_focused) {
this.value = "";
}
if (!this.disabled && !_validate.call(this)) {
ret = false;
}
});
return ret;
}
f = null;
});
$e('[validate]').each(function() {
this.onfocus = function() { ! this._ever_focused && _this.water_mark.hide(this);
this._ever_focused = true;
_this.validate_tip(this, "hide");
}
this.onblur = function() {
_validate.call(this, true);
}
});
},
getStrLen: function(str) {
return Math.ceil(str.replace(/[^x00-xff]/g, 'TS').length / 2);
}
},
upload: {
_uploadIframe: null,
_dialog: null,
apc_upload_id:null,
post_url:null,
dimension:"",
isprocessing:false,
showUpload: function(post_url, suc_fn, desc, type_param, no_size,dimension, opt) {
if (this._dialog) {
return;
}
//document.domain='mofing.com';
OP_COMMON.upload.dimension=dimension;
OP_COMMON.upload.post_url=post_url;
if(post_url.indexOf("?")!=-1){
post_url=post_url+"&act=frame";
}else{
post_url=post_url+"?act=frame";
}
var name = "文件";
if (this._uploadIframe == null) {
var iframe = $('#__FormTargetFrame');
if (iframe.length==0) {
iframe = document.createElement('iframe');
iframe.border = iframe.width = iframe.height = 0;
iframe.id = '__FormTargetFrame';
iframe.name = '__FormTargetFrame';
document.body.appendChild(iframe);
if (window.frames) {
window.frames['__FormTargetFrame'].name = '__FormTargetFrame';
}
}
this._uploadIframe = iframe;
}
this._uploadIframe.callback = function(ret) {
var _d = null;
OP_COMMON.upload.isprocessing=false;
QZFL.widget.msgbox.hide();
$( "#upload_file_process" ).hide();
if (0 == ret.error || true == ret.result) {
OP_COMMON.upload.closeUpload();
QZFL.widget.msgbox.show(ret.message || "上传成功",4, 2000);
suc_fn && suc_fn(ret);
} else {
var op_mask_ind = OP_COMMON.util.showMask(6500);
var crop=[];
var buttonConfigs=[{
type: QZFL.dialog.BUTTON_TYPE.Normal,
text: '重新上传',
tips: '重新上传',
clickFn: function() {
_d.unload();
_d = null;
}
},
{
type: QZFL.dialog.BUTTON_TYPE.Cancel,
text: '取消',
tips: '取消',
clickFn: function() {
OP_COMMON.upload.closeUpload();
_d = null;
}
}];
//固定尺寸的图片,才允许切割
if(ret.error==7 && OP_COMMON.upload.dimension != ""){
QZFL.css.insertCSSLink("./css/jquery.Jcrop.css");
ret.message+="或者裁剪图片";
crop={
type: QZFL.dialog.BUTTON_TYPE.Cancel,
text: '裁剪图片',
tips: '裁剪图片',
clickFn: function() {
_d.cropImage(ret.filePath);
}
};
buttonConfigs.unshift(crop);
}
_d = parent.QZFL.dialog.create("提示", '<p style="padding:30px 25px 0; line-height:22px; color:#f30;">上传失败:' + ret.message + '</p>', {
showMask: false,
'width': 320,
'height': 100,
buttonConfig:buttonConfigs
});
_d.cropImage=function(url){
//打开裁剪窗口
OP_COMMON.upload.cropImage(url);
_d = null;
};
_d.onUnload = function() {
OP_COMMON.util.hideMask(op_mask_ind);
};
}
};
var timestamp=new Date().getTime();
OP_COMMON.upload.apc_upload_id=V.util.getToken()+"_"+timestamp;
var html = ['<div style="text-align:left; padding-top:37px;">',
'<form method="post" action="' + post_url + '" enctype="multipart/form-data" target="__FormTargetFrame" id="formUpload">',
(no_size ? '': '<input type="hidden" name="imagesize" value="' + type_param+ '"/>'),
'<input type="hidden" name="dimension" value="', dimension, '" />',
'<input type="hidden" name="g_tk" value="', V.util.getToken(), '" />',
' <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" id="progress_key" value="'+OP_COMMON.upload.apc_upload_id+'"/>',
'<input type="hidden" name="token" value="', V.util.getToken(), '" />',
'<input type="hidden" name="appid" value="', parseInt(V.util.getUrlParam("appid")), '" />',
(opt && opt.customContent) || '',
'<div id="divUploadForm" style="height:100px;">',
'<div style="padding:0px 35px;">',
'<div id="upload_file_process"><div class="progress-label">Loading...</div></div>', '<p style="color:#000;">' + desc + '</p>',
'<input name="file" type="file" style="width:300px;padding:4px 0;margin-top:18px;background-color:#fff;" id="formUploadFile"/>',
'</div>', '</div>', '<div class="layer_opensns_confirm_bt">',
'<button type="submit" onclick="return (window.frames[0].OP_COMMON || OP_COMMON).upload.startProgress();" >确定</button>',
'<button type="button" onclick="(window.frames[0].OP_COMMON || OP_COMMON).upload.closeUpload(); ">取消</button>',
'</div>', '</form>', '</div>'].join('');
var win = QZFL.userAgent.ie == 6 ? window: parent;
var dialog = win.QZFL.dialog.create('上传' + name, html, 400, 174);
var maskID = win.QZFL.maskLayout.create();
dialog.onUnload = QZFL.object.bind(this,
function() {
win.QZFL.maskLayout.remove(maskID);
this._dialog = null;
});
this._dialog = dialog;
},
closeUpload: function() {
this._dialog && this._dialog.unload();
},
cropImage:function(url_obj){
$.getScript("./js/jquery.Jcrop.js",function(){
url="./"+url_obj;
var i_width, i_height;
$("<img/>") // 在内存中创建一个img标记
.attr("src", url)
.load(function() {
i_width = this.width;
i_height = this.height;
var w2=500;
var h2=500;
if(OP_COMMON.upload.dimension=="" || i_width<s_width || i_height<s_height){
QZFL.widget.msgbox.show("图片太小或者尺寸不规则,无法裁剪!",3, 2000);
//alert("");
return false;
}
var size_arr = OP_COMMON.upload.dimension.split("_");
var s_width=size_arr[0];
var s_height=size_arr[1];
if(i_width>i_height){
h2=w2*i_height/i_width;
}else{
w2=h2/i_height*i_width;
}
var html='<div class="crop_main" id="id_crop_main" style="padding-left: 20px;"><img id="image_crop_panel" src="'+url+'" style="width:'+w2+'px;height:'+h2+'px"/><span id="crop_preview_box" class="crop_preview"><img id="crop_preview" src="'+url+'" /></span></div>';
var win = QZFL.userAgent.ie == 6 ? window: parent;
var cropdialog = win.QZFL.dialog.create('裁剪图片' , html, {
showMask: false,
'width': w2+200,
'height':h2+20,
buttonConfig: [{
type: QZFL.dialog.BUTTON_TYPE.Normal,
text: '保存图片',
tips: '保存图片',
clickFn: function() {
//提交裁剪
QZFL.widget.msgbox.show("正在努力裁剪中...", 6, 10*1024*1024);
$("#crop_form").submit();
setTimeout(function(){cropdialog.unload();},500);
}
}, {
type: QZFL.dialog.BUTTON_TYPE.Cancel,
text: '取消',
tips: '取消',
clickFn: function() {
OP_COMMON.upload.closeUpload();
_d = null;
}
}]});
//增加表单
$("#id_crop_main").append('<div style="display:none;"><form action="cropimage.html" method="post" target="__FormTargetFrame" id="crop_form">'+
'<input type="hidden" name="filepath" value="'+url_obj+'"/>'+
'<input type="hidden" name="s_width" value="'+w2+'"/>'+
'<input type="hidden" name="s_height" value="'+h2+'"/>'+
'<input type="hidden" id="x" name="x" value="0"/><input type="hidden" id="y" name="y" value="0"/>'+
'<input type="hidden" id="w" name="w" value="'+s_width+'"/><input type="hidden" id="h" name="h" value="'+s_height+'"/> <input type="sumbit" value="确认剪裁" id="crop_submit" /></form></div>');
$("#image_crop_panel").Jcrop({
onChange:OP_COMMON.upload.showPreview,
onSelect:OP_COMMON.upload.showPreview,
aspectRatio:1,
allowSelect:!1,
setSelect: [0,s_width,s_height,0]
});
}) ;
});
},
showPreview:function(coords){
if(parseInt(coords.w) > 0){
$("#id_crop_main #x").val(coords.x);
$("#id_crop_main #y").val(coords.y);
$("#id_crop_main #w").val(coords.w);
$("#id_crop_main #h").val(coords.h);
//计算预览区域图片缩放的比例,通过计算显示区域的宽度(与高度)与剪裁的宽度(与高度)之比得到
var rx = $("#crop_preview_box").width() / coords.w;
var ry = $("#crop_preview_box").height() / coords.h;
//通过比例值控制图片的样式与显示
$("#crop_preview").css({
width:Math.round(rx * $("#image_crop_panel").width()) + "px", //预览图片宽度为计算比例值与原图片宽度的乘积
height:Math.round(rx * $("#image_crop_panel").height()) + "px", //预览图片高度为计算比例值与原图片高度的乘积
marginLeft:"-" + Math.round(rx * coords.x) + "px",
marginTop:"-" + Math.round(ry * coords.y) + "px"
});
}
},
startProgress:function(){
//检查是否选择了文件
var ff = $("form#formUpload #formUploadFile").val();
if(!ff){
QZFL.widget.msgbox.show("请选择文件!",3, 2000);
return false;
}
if(OP_COMMON.upload.isprocessing){
return false;
}
OP_COMMON.upload.isprocessing=true;
//如果支持html5,则显示进度条,否则直接进入表单
var isallow=OP_COMMON.uploadprogress.allowbrowser();
if(isallow){
OP_COMMON.uploadprogress.xmlHttp=OP_COMMON.uploadprogress.createXHR();
$( "#upload_file_process" ).show();
setTimeout(function(){
OP_COMMON.uploadprogress.progress();
}, 1000);
$( "#upload_file_process" ).progressbar({
value: false,
change: function() {
$(".progress-label" ).text( $(this).progressbar( "value" ) + "%" );
}
});
$(".progress-label" ).show();
return false;
}else{
//打开loading
QZFL.widget.msgbox.show("正在努力上传...", 6, 10*1024*1024);
return true;
}
}
},
init: function(data) {
if (data.tips) {
QZFL.each(data.tips,
function() {
var t = this;
QZFL.dom.createElementIn("div", $('j_top_caution'), false, {
"class": 0 == t.type ? "fn_hint": "fn_hint fn_hint_success",
"innerHTML": '<i class="' + (0 == t.type ? 'ico ico_hint_advise': 'ico ico_hint_success') + '"></i> <p>' + t.content + '</p>'
});
});
}
},
uploadprogress:{
xmlHttp:null,
allowbrowser:function(){
var bro={
"msie":10,
"safari":5.02,
"mozilla":4,
"webkit":6
};
var version=parseFloat($.browser.version);
if ($.browser.safari) {
return version>=bro.safari;
}else if($.browser.msie){
return version>=bro.msie;
}else if($.browser.mozilla){
return version>=bro.mozilla;
}else if($.browser.webkit){
return version>=bro.webkit;
}
return false;
},
Try : {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
}
},
createXHR:function(){
return OP_COMMON.uploadprogress.Try.these(
function() {return new XMLHttpRequest();}
) || false;
},
progress:function(id){
var xmlHttp=OP_COMMON.uploadprogress.xmlHttp;
var fd = new FormData();
//formUpload
fd.append("file", document.getElementById('formUploadFile').files[0]);
fd.append("g_tk", document.getElementsByName('g_tk')[0].value);
fd.append("token", document.getElementsByName('token')[0].value);
fd.append("imagesize", document.getElementsByName('imagesize')[0].value);
fd.append("dimension", document.getElementsByName('dimension')[0].value);
xmlHttp.upload.addEventListener("progress", OP_COMMON.uploadprogress.listeners.uploadProgress, false);
xmlHttp.addEventListener("load", OP_COMMON.uploadprogress.listeners.uploadComplete, false);
xmlHttp.addEventListener("error", OP_COMMON.uploadprogress.listeners.uploadFailed, false);
xmlHttp.addEventListener("abort", OP_COMMON.uploadprogress.listeners.uploadCanceled, false);
xmlHttp.open("POST",OP_COMMON.upload.post_url);
xmlHttp.send(fd);
},
listeners:{
uploadProgress:function(evt){
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
$( "#upload_file_process" ).progressbar("value",percentComplete);
}
},
uploadComplete:function(evt){
//直接调用表单回调函数
//json转换
var result= jQuery.parseJSON(evt.target.responseText);
OP_COMMON.upload._uploadIframe.callback(result);
//alert(evt.target.responseText);
},
uploadFailed:function(evt){
//alert("There was an error attempting to upload the file.");
},
uploadCanceled:function(evt){
//alert("The upload has been canceled by the user or the browser dropped the connection.");
}
}
},
bind_events: function() {
QZFL.event.delegate(document.body, '[_op_tip]', 'mouseover',
function() {
var opts = OP_COMMON.OP_TIPS[this.getAttribute("_op_tip")];
parent.openTips.show(this, opts, window);
});
QZFL.event.delegate(document.body, '[_op_tip]', 'mouseout',
function() {
parent.openTips.hide(window);
});
}
};
示例:http://www.cjblog.org/uploadcrop/index.html
源码下载:http://www.cjblog.org/uploadcrop/uploadcrop.rar
非常感谢 张鑫旭 提供的Jcrop插件