网上搜了一下,无非就是基于flash组件、juqery插件来完成,基于您可能不需要jquery,想试一下javascrpit原生图片上传。
文件上传
1、传统形式
文件上传的传统形式,是使用表单元素file:
<form id="upload-form" action="upload.php" method="post" enctype="multipart/form-data" >
<input type="file" id="upload" name="upload" /> <br />
<input type="submit" value="Upload" />
</form>
传统的表单上传,属于"同步上传"。也就是说,点击上传按钮后,网页"锁死",用户只能等待上传结束,然后浏览器刷新,跳到表单的action属性指定的网址。
2、iframe上传
iframe上传为异步方式,主要是表单添加target属性,用户点击submit时,指向iframe窗口。
<form id="upload-form" target="update_img" action="/upload?type=iframe&flag=7&callback=getImgSrc" method="post" enctype="multipart/form-data">
<input type="file" class="ieinput" id="ieinput" name="FileUploadForm[file]">
<input type="submit" value="Upload">
</form>
<iframe frameborder="0" scrolling="no" id="update_img" name="update_img" src="about:blank" style="height:0;width:0;overflow:hidden;"></iframe>
这使得上传结束后,服务器将结果返回iframe窗口,所以当前页面就不会跳转了。其次,它在action属性指定的上传网址的后面,添加了一个参数,使得服务器知道回调函数的名称。这样就能将服务器返回的信息,从iframe窗口传到上层页面。
服务器(upload.php)返回的信息,应该是如下形式:
<script type="text/javascript">
window.top.window['callback'](data);
</script>
3、ajax上传
HTML5提出了XMLHttpRequest对象的第二版,从此ajax能够上传文件了。这是真正的"异步上传",是将来的主流。上面的iframe上传,可以用作老式浏览器的替代方案。ajax上传主要用的是FormData对象,它能够构建类似表单的键值对。
// 检查是否支持FormData
if(window.FormData) {
var formData = new FormData();
// 建立一个upload表单项,值为上传的文件
formData.append('upload', document.getElementById('upload').files[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', $(this).attr('action'));
// 定义上传完成后的回调函数
xhr.onload = function () {
if (xhr.status === 200) {
console.log('上传成功');
} else {
console.log('出错了');
}
};
xhr.send(formData);
}
关于图片上传中的进度条、图片预览、拖放上传请移步阮老师的文件上传的渐进式增强。
实操
1、ajax上传需要用到FormData对象,它的兼容性IE堪忧。
所以需要判断是IE浏览器版本使用iframe上传。
const isIe = function(){
return (navigator.userAgent.indexOf("Edge") == -1) && ( !!window['ActiveXObject'] || "ActiveXObject" in window );
}();
2、项目中本来就是一个原生form提交表单,而iframe上传图片也需要一个form,所以页面结构大体是这样的,在form外再放一个form
<form target="_self" enctype="multipart/form-data" id="account" action="/create/19" method="post">
<div class="kfstit"><h3>帐号修改内容</h3></div>
<table class="tableForm">
.....
<tr>
<th>手持身份证照片</th>
<td>
<span class="upfiles">
<i class="uppr">
<input type="file" accept="image/jpeg,image/jpg,image/png" id="fileupload" name="FileUploadForm[file]" multiple>
<label class="Iechange" for="ieinput"></label>
</i>
</span>
<span class="musts">*</span>
<span class="formTips"></span>
</td>
</tr>
......
</table>
<div class="kfstit"><h3>联系方式</h3></div>
<table class="tableForm">
.....
</table>
</form>
<form id="upload-form" target="update_img" action="/upload?type=iframe&flag=7&callback=uploadResult" method="post" enctype="multipart/form-data">
<input type="file" class="ieinput" id="ieinput" name="FileUploadForm[file]">
</form>
<iframe frameborder="0" scrolling="no" id="update_img" name="update_img" src="about:blank" style="height:0;width:0;overflow:hidden;"></iframe>
ajax上传用真正的ID为fileupload的input触发,IE下用ID为ieinput的lable标签来触发。
//如果是IE浏览器给uppr父标签添加ie类名,让label显示,input标签隐藏
if(isIe) query.addClass(query.getByClass('uppr',this.wrap)[0],'ie');
query.add(document.getElementById('fileupload'),'change',event=>{
this.changeInput( query.getTarget(event) );
});
private async changeInput(target){
if(!target && !target.files) return;
query.forEach(target.files,item=>{
if(item.size > 1024*1024*2){
//...照片大小大于2M,请重新选择照片!
}else{
const fd = new FormData();
fd.append('flag', '7');
fd.append('FileUploadForm[file]',item);
const data = await post({
url:'/upload',
data:fd
})
// [
// {
// size: 122388,
// url: "/static/27ca29f827598a4c6e683f0ad70a92c20ca4d238.jpg"
// }
// ]
}
});
}
这里的query是一个自定义js常用基础库。
3、IE9及以下上传附件时报***.submit()拒绝访问?
刚开始ID为ieinput的lable标签,其实是一个span标签,通过点击span标签。来触发外面form里file.click()弹出文件选择控件。这时在E9及以下报***.submit()拒绝访问?网上的说法是file.click()会触发浏览器js安全性问题所以拒绝。灵光闪动利用lable的for来触发file的change事件试试:
query.add(document.getElementById('ieinput'),'change',event=>{
const target = query.getTarget(event);
if(target.value) (<HTMLFormElement>document.getElementById('upload-form')).submit();
});
window['uploadResult'] = data=>{
// [
// {
// size: 122388,
// url: "/static/27ca29f827598a4c6e683f0ad70a92c20ca4d238.jpg"
// }
// ]
}
这里的query是一个自定义js常用基础库。
4、文件上传multipart/form-data
这里要注意的细节ajax上传时,send参数一定是一个formData对象,而不是把formData对象序列化get网址传递,当send一个formData对象时浏览器会自动设置Content-Type字段为multipart/form-data。
xhr.send(formData);
5、因为项目时间紧,只做了图片上传功能,关于图片预览功能也可参考司徒正美的前端图片预览,上传前预览,兼容IE7、8、9、10、11,Firefox,Chrome。