作者:水歌
链接:https://www.zhihu.com/question/21452742/answer/34164634
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://www.zhihu.com/question/21452742/answer/34164634
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以下是
网上搜索文档、团队实战经验的总结,主要基于 Android 4.0+、iOS 6.0+、微信 5.2+ ——
再分享一段我手写的 Input File 图片友好版 v0.5 的代码( jQuery 插件)——
其对应的 HTML 结构是 ——
对于 DOM/JS 层面实在无法直接支持文件控件的,有两种备用方案 ——
【插件备注】
若用户多次点开文件选择对话框,但都没选择文件时(即 Change 事件从未触发),本插件可能也会判断为“当前浏览器文件控件被屏蔽”。
- 过去限制很多的 iOS 版微信 却没出什么大问题,反倒 Android 各版本的适配让我们各种加班
- 较新版本的微信并没有对 HTML 原生文件控件做限制,只是它默认调用 Android 系统自带的 WebView,限制是怎样的取决于相应版本 Android 的官方代码(有说法是出于安全考虑)
- 除了 Android v4.4.2 这个中间版本(小米 3、红米 Note 等机型的出厂系统),其它 v4.x 版本的 WebView 基本都可以使用 原生文件控件
- 若同机安装有 QQ浏览器,微信可以调用它修缮过的内核,就可以正常使用文件控件(但必须在安装 QQ浏览器之后重启微信才行)
- 如有某版本的 WebView 不能用文件控件,它的拦截是在底层进行的,所以 JavaScript 引擎层面并无异常抛出,不会中断程序的执行
再分享一段我手写的 Input File 图片友好版 v0.5 的代码( jQuery 插件)——
// -------------------------------------------------- //
//
// >>> Input-File 图片友好版 <<<
//
//
// [Based on] jQuery, jQuery.Browser.js
//
// [Version] v0.5 (2015-7-3 14:26:30)
//
//
// (C)2014-2015 test_32@fyscu.com
//
// -------------------------------------------------- //
(function (BOM, DOM, $) {
var URL_Object = BOM.webkitURL || BOM.URL || BOM;
$.fn.xImage = function (Type_Filter) {
var $_This = this.find('*').addBack().filter('input[type="file"]');
Type_Filter = Type_Filter || [ ];
$_This.parent().css({
position: 'relative',
cursor: 'pointer'
});
$_This
.css({
position: 'absolute',
'z-index': 999,
opacity: 0
})
.each(function () {
var $_This = $(this);
var $_PreView = $_This.siblings('img, img.PreView').eq(0);
if (! $_PreView.length)
$_PreView = $('<img />').before($_This);
$_PreView.addClass('PreView').css({
display: 'inline-block',
'max-height': $(top).height() * (1 / 3),
'max-width': $(top).width() * (1 / 3)
})
.on('Ready', function () {
$_This.css({
top: $_PreView.position().top,
left: $_PreView.position().left,
width: $_PreView.width(),
height: $_PreView.height()
});
}).trigger('Ready').on('load', function () {
$_PreView.trigger('Ready');
});
})
.data('clicks', 0).click(function () {
var $_This = $(this);
var Click_Times = $_This.data('clicks');
if ($.browser.mobile && (++Click_Times > 3)) {
BOM.alert("您当前的浏览器无法在本页上传文件……");
return false;
}
$_This.data('clicks', Click_Times);
})
.change(function () {
var $_This = $(this).data('clicks', 0);
try {
var iFile = arguments[0].target.files[0];
} catch (iError) {
BOM.alert([
"您当前 浏览器内核 较为古老,暂不支持【图片上传预览】……",
"建议更换为最新版 搜狗、猎豹、傲游 等双核浏览器~"
].join("\n\n"));
$_This.show().siblings('img.PreView').remove();
return true;
}
var iType = iFile.type.split('/');
if (iType[0] != 'image') {
BOM.alert("您所选的文件不是图片……");
return false;
} else if ($.inArray(iType[1], Type_Filter) > -1) {
BOM.alert([
"此处不能上传", iType[1].toUpperCase(), "格式的图片!"
].join(' '));
return false;
}
var iReader = new FileReader();
iReader.onload = function () {
$_This.siblings().not('img.PreView, input[type="file"]').hide();
var $_PreView = $_This.siblings('img.PreView');
$_PreView[0].onload = function () {
URL_Object.revokeObjectURL(this.src);
};
$_PreView[0].src = URL_Object.createObjectURL(iFile);
};
iReader.readAsBinaryString(iFile);
});
return this;
};
})(self, self.document, self.jQuery);
<form method="POST" action="./xxx">
<div class="ImageBox">
<input type="file" />
<span>上传美照</span>
</div>
<button type="submit">完成</button>
</form>
<script>
// 原生文件上传控件“图片友好化”,
// 并排除一些服务器处理不了的格式
$('.ImageBox').xImage(['psd', 'webp', 'bpg']);
</script>
对于 DOM/JS 层面实在无法直接支持文件控件的,有两种备用方案 ——
- 引导失败的用户在其微信公众平台的主界面消息框中发送图片消息,服务器端做好相应接口支持
- 指导用户下载安装 QQ浏览器并重启微信(微信内下载只有 腾讯应用宝的链接可正常使用,否则就只能再打开一个下载网页并引导用户在其它手机浏览器中打开它去下载)
【插件备注】
若用户多次点开文件选择对话框,但都没选择文件时(即 Change 事件从未触发),本插件可能也会判断为“当前浏览器文件控件被屏蔽”。