-
我尝试过的办法
- 首先是<input type=”file”>,这是我们最容易,同时也是最先用的,应该也是我试过那么多的插件都是用这个,这个只有在部分手机的微信版本上会显示upload disable,大部分手机微信还是支持的,但是做完我们会发现我们的微信可以选择文件,但是上传不了,百度了一下很多人说这个被腾讯给“阉割”掉了,一开始我也是这么觉得,所以就放弃了选择这个,后来发现,腾讯“阉割”掉了的不是<input type=”file”>,而是你上传往服务器发请求的那一块,具体怎么解释我是新手,真心不造怎么说,后面会再说,希望知道这个原理的能和我说明一下。
- 放弃了<input type=”file”>,我们工作室的师兄就推荐我一款插件,叫Uploadify,这款插件在它的官网上面有两种版本,一种是flash(免费),一种是html5(收费),不过也有大牛把html5的版本模仿了出来,网上找得到。首先是flash吧,这个也是另外一篇博文里博主推荐大家的方法(原文地址:http://blog.csdn.net/zz880329/article/details/12652063),我就尝试了一下,发现使用flash实现上传的话,选择文件的“样式”变了,变成了flash的选择文件,大家自己试过的话应该就会发现,flash选择文件的方式你看到的只有文件名,你都不知道自己要选哪张图片好,而且好像还需要手机有flash支持,所以这个flash被我放弃了。然后是html5的版本,打开demo的代码,上面确实没有了<input type=”file”>,但是实际运行起来,在网页还是用的是了<input type=”file”>,实际放到微信上好像也是行不通,后来也就放弃了。
- 后面又看到一篇介绍各种HTML5的上传插件的博文,然后又是像无头苍蝇那样各种尝试,最终只保留下了其中一种我觉得是最可行的,但是好像兼容性各方面还有待优化,后面我的第二种可行办法我会再介绍它的,希望大家都说下各自的理解吧,还有好多方面我都不太懂。
-
第一种可行的js插件
- 尝试过很多插件之后,基本都以失败告终。不过好像每次写代码都很幸运,我舍友在微信上找到一个网站是有实现相关功能的,然后我就去找到那个网站研究他们的上传插件,发现使用的插件我之前没有尝试过,于是就找到了这个插件并且成功实现功能,插件叫ajaxfileupload.js
- // JavaScript Document
jQuery.extend({
createUploadIframe: function(id, uri)
{
//create frame
var frameId = 'jUploadFrame' + id;
if(window.ActiveXObject) {
var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
if(typeof uri== 'boolean'){
io.src = 'javascript:false';
}
else if(typeof uri== 'string'){
io.src = uri;
}
}
else {
var io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
}
io.style.position = 'absolute';
io.style.top = '-1000px';
io.style.left = '-1000px';
document.body.appendChild(io);
return io;
},
createUploadForm: function(id, fileElementId)
{
//create form
var formId = 'jUploadForm' + id;
var fileId = 'jUploadFile' + id;
var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
var oldElement = jQuery('#' + fileElementId);
var newElement = jQuery(oldElement).clone();
jQuery(oldElement).attr('id', fileId);
jQuery(oldElement).before(newElement);
jQuery(oldElement).appendTo(form);
//set attributes
jQuery(form).css('position', 'absolute');
jQuery(form).css('top', '-1200px');
jQuery(form).css('left', '-1200px');
jQuery(form).appendTo('body');
return form;
},
ajaxFileUpload: function(s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = s.fileElementId;
var form = jQuery.createUploadForm(id, s.fileElementId);
var io = jQuery.createUploadIframe(id, s.secureuri);
var frameId = 'jUploadFrame' + id;
var formId = 'jUploadForm' + id;
if( s.global && ! jQuery.active++ )
{
// Watch for a new set of requests
jQuery.event.trigger( "ajaxStart" );
}
var requestDone = false;
// Create the request object
var xml = {};
if( s.global )
{
jQuery.event.trigger("ajaxSend", [xml, s]);
}
var uploadCallback = function(isTimeout)
{
// Wait for a response to come back
var io = document.getElementById(frameId);
try
{
if(io.contentWindow)
{
xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
}else if(io.contentDocument)
{
xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
}
}catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if( xml || isTimeout == "timeout")
{
requestDone = true;
var status;
try {
status = isTimeout != "timeout" ? "success" : "error";
// Make sure that the request was successful or notmodified
if( status != "error" )
{
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData( xml, s.dataType );
if( s.success )
{
// ifa local callback was specified, fire it and pass it the data
s.success( data, status );
};
if( s.global )
{
// Fire the global callback
jQuery.event.trigger( "ajaxSuccess", [xml, s] );
};
} else
{
jQuery.handleError(s, xml, status);
}
} catch(e)
{
status = "error";
jQuery.handleError(s, xml, status, e);
};
if( s.global )
{
// The request was completed
jQuery.event.trigger( "ajaxComplete", [xml, s] );
};
// Handle the global AJAX counter
if(s.global && ! --jQuery.active)
{
jQuery.event.trigger("ajaxStop");
};
if(s.complete)
{
s.complete(xml, status);
} ;
jQuery(io).unbind();
setTimeout(function()
{ try
{
jQuery(io).remove();
jQuery(form).remove();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
}, 100);
xml = null;
};
}
// Timeout checker
if( s.timeout > 0 )
{
setTimeout(function(){
if( !requestDone )
{
// Check to see ifthe request is still happening
uploadCallback( "timeout" );
}
}, s.timeout);
}
try
{
var form = jQuery('#' + formId);
jQuery(form).attr('action', s.url);
jQuery(form).attr('method', 'POST');
jQuery(form).attr('target', frameId);
if(form.encoding)
{
form.encoding = 'multipart/form-data';
}
else
{
form.enctype = 'multipart/form-data';
}
jQuery(form).submit();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if(window.attachEvent){
document.getElementById(frameId).attachEvent('onload', uploadCallback);
}
else{
document.getElementById(frameId).addEventListener('load', uploadCallback, false);
}
return {abort: function () {}};
},
uploadHttpData: function( r, type ) {
var data = !type;
data = type == "xml" || data ? r.responseXML : r.responseText;
// ifthe type is "script", eval it in global context
if( type == "script" )
{
jQuery.globalEval( data );
}
// Get the JavaScript object, ifJSON is used.
if( type == "json" )
{
eval( "data = " + data );
}
// evaluate scripts within html
if( type == "html" )
{
jQuery("<div>").html(data).evalScripts();
}
return data;
}
});
- 前端代码:
-
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1"> <script src="jquery-1.7.1.js" type="text/javascript"></script> <script src="ajaxfileupload.js" type="text/javascript"></script> <script type="text/javascript"> function ajaxFileUpload() { $.ajaxFileUpload ( { url: 'upload.aspx', //用于文件上传的服务器端请求地址 secureuri: false, //一般设置为false fileElementId: 'file', //文件上传空间的id属性 <input type="file" id="file" name="file" /> dataType: 'json', //返回值类型 一般设置为json success: function (data, status) //服务器成功响应处理函数 { $("#img1").attr("src", data.imgurl); if (typeof (data.error) != 'undefined') { if (data.error != '') { alert(data.error); } else { alert(data.msg); } } }, error: function (data, status, e)//服务器响应失败处理函数 { alert(e); } } ) return false; } </script> </head> <body> <input type="file" id="file" name="file" value="上传" accept="image/*;capture=camera" οnchange="ajaxFileUpload()"/> <p><img id="img1" alt="上传成功啦" src="" /></p> </body> </html>
但是现在微信6.2以后,也不好使了
第二种可行的办法,仅限用于图片,其他类型文件我还没尝试
-
接下来是第二种可行的办法,也是在找控件的过程中发现的,感觉很棒,我在三星的微信上试过可以实现上传,但是在魅族上页面还是出错了,之后由于第一种方法可以兼容,于是就采用了第一种,没有对第二种进行深究了,不过还是分享一下。它的原理就是把你点击选择完图片后,用js将你选择的图片转为base64格式的数据,而且还能实现使用js对图片进行压缩后保存下压缩后的base64格式的字符串数据,而我们只需要把这串字符串发送到后台,然后在后台将base64格式的数据转为图片就容易啦,这样,腾讯也抓不了。
-
前台代码,我跟原作者代码有修改了一点,因为发现发送到后台base64转图片的时候,base64编码不能带上“文件头”(/^data:base64,/),还有就是加上了压缩图片所需要修改的参数的位置,这里默认压缩为100*100。(原作者好腻害的赶脚)。
-
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"> <title>图片压缩</title> <script src="jquery-1.7.1.js" type="text/javascript"></script> <style> body { margin:0; padding:0; } html { font-size:62.5%; } .imgzip { padding:1em; } .imgzip .itm { padding-bottom:1em; word-break:break-all; font-size:1.2rem; line-height:1.5em; } .imgzip .itm .tit { margin-bottom:.5em; background-color:#e71446; color:#FFF; padding:.5rem 1rem; border-radius:3px; } .imgzip .itm .cnt { padding:1rem; } .imgzip .itm .cnt img { display:block; max-width:100%; } .imgzip textarea { width:100%; height:20em; } </style> </head> <body> <input type="file" accept="image/*;capture=camera" class="input"> <input type="button" value="上传" οnclick="upload();" /> <div class="imgzip"></div> <script> document.addEventListener('DOMContentLoaded', init, false); function init() { var u = new UploadPic(); u.init({ input: document.querySelector('.input'), callback: function (base64) { var html = ''; html = '<div class="itm"><div class="tit">图片名称:</div><div class="cnt" id="name">' + this.fileName + '</div></div>' + '<div class="itm"><div class="tit">原始大小:</div><div class="cnt">' + (this.fileSize / 1024).toFixed(2) + 'KB<\/div><\/div>' + '<div class="itm"><div class="tit">编码大小:</div><div class="cnt">' + (base64.length / 1024).toFixed(2) + 'KB<\/div><\/div>' + '<div class="itm"><div class="tit">原始尺寸:</div><div class="cnt">' + this.tw + 'px * ' + this.th + 'px<\/div><\/div>' + '<div class="itm"><div class="tit">编码尺寸:</div><div class="cnt">' + this.sw + 'px * ' + this.sh + 'px<\/div><\/div>' + '<div class="itm"><div class="tit">图片预览:</div><div class="cnt"><img src="' + base64 + '"><\/div><\/div>' + '<div class="itm"><div class="tit">Base64编码:</div><div class="cnt"><textarea id="base64">' + this.noHead + '<\/textarea><\/div><\/div>'; document.querySelector('.imgzip').innerHTML = html; }, loading: function () { document.querySelector('.imgzip').innerHTML = '读取中,请稍候...'; } }); } function UploadPic() { this.sw = 0; this.sh = 0; this.tw = 0; this.th = 0; this.scale = 0; this.maxWidth = 0; this.maxHeight = 0; this.maxSize = 0; this.fileSize = 0; this.fileDate = null; this.fileType = ''; this.fileName = ''; this.input = null; this.canvas = null; this.mime = {}; this.type = ''; this.callback = function () { }; this.loading = function () { }; this.noHead = ""; } UploadPic.prototype.init = function (options) { this.maxWidth = options.maxWidth || 800; this.maxHeight = options.maxHeight || 600; this.maxSize = options.maxSize || 3 * 1024 * 1024; this.input = options.input; this.mime = { 'png': 'image/png', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'bmp': 'image/bmp' }; this.callback = options.callback || function () { }; this.loading = options.loading || function () { }; this._addEvent(); }; /** * @description 绑定事件 * @param {Object} elm 元素 * @param {Function} fn 绑定函数 */ UploadPic.prototype._addEvent = function () { var _this = this; function tmpSelectFile(ev) { _this._handelSelectFile(ev); } this.input.addEventListener('change', tmpSelectFile, false); }; /** * @description 绑定事件 * @param {Object} elm 元素 * @param {Function} fn 绑定函数 */ UploadPic.prototype._handelSelectFile = function (ev) { var file = ev.target.files[0]; this.type = file.type // 如果没有文件类型,则通过后缀名判断(解决微信及360浏览器无法获取图片类型问题) if (!this.type) { this.type = this.mime[file.name.match(/\.([^\.]+)$/i)[1]]; } if (!/image.(png|jpg|jpeg|bmp)/.test(this.type)) { alert('选择的文件类型不是图片'); return; } if (file.size > this.maxSize) { alert('选择文件大于' + this.maxSize / 1024 / 1024 + 'M,请重新选择'); return; } this.fileName = file.name; this.fileSize = file.size; this.fileType = this.type; this.fileDate = file.lastModifiedDate; this._readImage(file); }; /** * @description 读取图片文件 * @param {Object} image 图片文件 */ UploadPic.prototype._readImage = function (file) { var _this = this; function tmpCreateImage(uri) { _this._createImage(uri); } this.loading(); this._getURI(file, tmpCreateImage); }; /** * @description 通过文件获得URI * @param {Object} file 文件 * @param {Function} callback 回调函数,返回文件对应URI * return {Bool} 返回false */ UploadPic.prototype._getURI = function (file, callback) { var reader = new FileReader(); var _this = this; // function tmpLoad() { // 头不带图片格式,需填写格式 var re = /^data:base64,/; var ret = this.result + ''; if (re.test(ret)) ret = ret.replace(re, 'data:' + _this.mime[_this.fileType] + ';base64,'); //此处为自己加上的去掉base64不带“头”的判断 if (ret.indexOf(";base64,") >= 0) { var num = ret.indexOf(";base64,"); num = parseInt(num) + 8; _this.noHead = ret.substring(num); } callback && callback(ret); } reader.onload = tmpLoad; reader.readAsDataURL(file); return false; }; /** * @description 创建图片 * @param {Object} image 图片文件 */ UploadPic.prototype._createImage = function (uri) { var img = new Image(); var _this = this; function tmpLoad() { _this._drawImage(this); } img.onload = tmpLoad; img.src = uri; }; /** * @description 创建Canvas将图片画至其中,并获得压缩后的文件 * @param {Object} img 图片文件 * @param {Number} width 图片最大宽度 * @param {Number} height 图片最大高度 * @param {Function} callback 回调函数,参数为图片base64编码 * return {Object} 返回压缩后的图片 */ UploadPic.prototype._drawImage = function (img, callback) { // this.sw = img.width; // this.sh = img.height; //如果不需要压缩可将上面注释与下面的更换; this.tw = img.width; this.th = img.height; this.sw = 100; this.sh = 100; this.scale = (this.tw / this.th).toFixed(2); if (this.sw > this.maxWidth) { this.sw = this.maxWidth; this.sh = Math.round(this.sw / this.scale); } if (this.sh > this.maxHeight) { this.sh = this.maxHeight; this.sw = Math.round(this.sh * this.scale); } this.canvas = document.createElement('canvas'); var ctx = this.canvas.getContext('2d'); this.canvas.width = this.sw; this.canvas.height = this.sh; ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, this.sw, this.sh); this.callback(this.canvas.toDataURL(this.type)); ctx.clearRect(0, 0, this.tw, this.th); this.canvas.width = 0; this.canvas.height = 0; this.canvas = null; }; function upload() { var base64 = $("#base64").val(); var name = $("#name").text(); $.ajax( { type: "post", url: "Upload.ashx", data: { base64: base64, name: name }, async: true, success: function fun(rt) { alert(rt); } }); }; </script> </body> </html>