在Extjs开发中,图片上传预览是一个常见需求,但许多开发者会遇到一个经典陷阱:用户选择图片后,预览区域漆黑一片,没有任何显示。根本原因在于浏览器安全策略禁止直接将本地文件路径赋值给img标签的src属性。绕过这一限制的有效方案,是利用微软的AlphaImageLoader滤镜间接加载本地图片,从而实现稳定的预览效果。
具体实现步骤如下:首先配置一个带文件上传功能的表单控件,参考以下代码:
Extjs文件上传控件配置示例
{ width: 450, fileUpload: true, fieldLabel: '选择图片', items: [{ xtype: 'textfield', id: 'up_forth', name: 'up_forth', inputType: 'file', width: 300 }] }
这里的关键是必须设置fileUpload: true,否则表单提交时会出现编码错误。接下来需要一个预览容器,本例使用box组件嵌入一个div,尺寸固定为150×150像素:
预览容器配置代码
{ columnWidth: .18, bodyStyle: ' margin:4px 10px 10px 5px', layout: 'form', items: [{ xtype: 'box', autoEl: { width: 150, height: 150, tag: 'div', id: 'browser_up_forth' } }] }
预览容器的id与上传控件的id存在对应关系——上传控件id为up_forth,则容器id为browser_up_forth,后续函数中将基于此规则动态拼接生成完整id。
核心实现逻辑封装在下面的preview函数中。调用时需传入两个参数:外层FormPanel以及上传控件的id,例如preview(myform, 'up_forth')。特别要注意绑定时机:应在FormPanel的render事件内为上传控件添加change监听,确保控件渲染完成后才挂载事件。
预览核心函数实现
var preview = function (myform, control_id) { var img_reg = /.([jJ][pP][gG]){1}$|.([jJ][pP][eE][gG]){1}$|.([gG][iI][fF]){1}$|.([pP][nN][gG]){1}$|.([bB][mM][pP]){1}$/ myform.on('render', function (f) { myform.form.findField(control_id).on('render', function () { Ext.get(control_id).on('change', function (field, newValue, oldValue) { var obj = Ext.get(control_id).dom; var url = getFullPath(obj); if (img_reg.test(url)) { var newPreview = Ext.get('browser_' + control_id).dom; var showPic = Ext.get("showPic_" + control_id); if (showPic != null) { showPic.remove();//删除原来的图片 } var imgDiv = document.createElement("div"); imgDiv.id = "showPic_" + control_id; document.body.appendChild(imgDiv); imgDiv.style.width = "150px"; imgDiv.style.height = "150px"; imgDiv.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod = scale)"; imgDiv.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = url; newPreview.appendChild(imgDiv); } }, this); }, this); }, this); } //得到图片地址 function getFullPath(obj) { if (obj) { // ie if (window.na vigator.userAgent.indexOf("MSIE") >= 1) { obj.select(); return document.selection.createRange().text; } // firefox else if (window.na vigator.userAgent.indexOf("Firefox") >= 1) { if (obj.files) { return obj.files.item(0).getAsDataURL(); } return obj.value; } return obj.value; } }
这里有几个关键细节值得注意:
- 正则表达式
img_reg用于过滤文件类型,仅允许jpg、jpeg、gif、png、bmp等常见图片格式。 - 获取文件路径时,IE与其他浏览器需采用不同分支:IE使用
document.selection,Firefox(以及Chrome等现代浏览器)应使用getAsDataURL方法。不过当前写法仅兼容Firefox,实际项目中可扩展支持Chrome的FileReader API,此处仅演示核心思路。 - 预览功能依赖AlphaImageLoader滤镜,该方案仅支持IE浏览器。因此本方法主要解决IE环境下的图片预览问题。对于现代浏览器,直接使用FileReader即可轻松实现,但大量遗留项目仍需兼容IE。
整体实现逻辑清晰:通过change事件捕获用户选择的文件变化,获取本地路径,再借助滤镜将图片投射到div中。预览框的宽高与滤镜的sizingMethod=scale参数配合,图片会自动缩放适配。实际使用时,务必确保FormPanel的fileUpload设置为true,否则上传功能将失败。
