利用iframe无刷新上传文件的坑
原文:利用iframe无刷新上传文件的坑

页面里经常要用到文件上传的功能,而且要求页面不刷新,先说一下原理:页面里放一个file控件和submit按钮,外面用form表单包住,给form表单加上对应的属性值,action、method、entype、name,到这一步,能上传文件了,但是这样上传文件会刷新页面,这不是我们想要的。我们要的是文件上传时不刷新页面,那么也简单,在页面里放一个iframe,设置它的宽高为0,这里有两个坑:

1、需要设置iframe的name值与form的target属性值一样,意思就是把form表单上传文件的刷新转嫁到iframe里去了;

2、form表单的enctype属性值必须设置成multipart/form-data,将文件转换成文件流供后端接收;

代码如下:

<iframename="fileUpload"></iframe>
<formmethod="post"action="xxxx"enctype="multipart/form-data"name="fileForm"target="fileUpload"><inputtype="file"class="fileInput"name="fileInput"><inputtype="submit"value="提交" />
</form>

页面(这里为了看到效果,就不将iframe的宽高设为0了):

事情就这么愉快地结束了吗?当然没有,离国庆节还有那么些天,不要着急。

到这里文件能上传了,页面也不会刷新,那么还差什么?当然是精益求精--优化啦。怎么优化?假如页面里有三个地方需要上传不同类型的文件,最好的办法肯定不是在页面里将代码copy三份,然后就这样用,这是普通开发的做法,我们可以利用js动态生成上面这些代码,需要上传文件的地方,一个函数加参数就搞定了,代码如下:

/*2014年9月18日17:39:47 By 王美建*/
functionajaxUpload(opt){/*参数说明:opt.frameName : iframe的name值;opt.url : 文件要提交到的地址;opt.fileName : file控件的name;opt.format : 文件格式,以数组的形式传递,如['jpg','png','gif','bmp'];opt.callBack : 上传成功后回调;*/var iName=opt.frameName; //太长了,变短点variframe,form;//创建iframe和form表单iframe = $('<iframe name="'+iName+'" />');form= $('<form method="post" style="display:none;" target="'+iName+'" action="'+opt.url+'"  name="form_'+iName+'" enctype="multipart/form-data" />');file= $('<input type="file" name="'+opt.fileName+'" />');file.appendTo(form);//插入body
$(document.body).append(iframe).append(form);//触发浏览事件,选择文件
file.click();//选中文件后,验证文件格式是否符合要求file.change(function(){//取得所选文件的扩展名var fileFormat=$(this).val().exec(/\.[a-zA-Z]+$/)[0].substring(1);if(opt.format.join('-').indexOf(fileVal)!=-1){form.submit();//格式通过验证后提交表单;}else{iframe.remove();form.remove();alert('文件格式错误,请重新选择!');}});//文件提交完后iframe.load(function(){var data = $(this).contents().find('body').html();opt.callBack(data);iframe.remove();form.remove();})
}

使用方法:在页面里放一个按钮Btn,点击Btn时触发ajaxUpload方法,ajaxUpload方法内部自动创建上传所需要的元素并自动触发file.click()事件供用户选择文件,选中文件后自动验证文件格式并提交,然后返回后端返回的结果,到这里,问题解决了80%,为什么不是100%?ajaxUpload方法在IE8以上及火狐、chrome浏览器都没有问题,但在IE8及以下的浏览器上传文件会提示:没有权限!这是因为低版本的IE做了安全限制,file控件必须由用户主动点击触发选择的文件才可以上传,而不能使用js的click事件来模拟点击触发。在此我又想说,IE我~!@#¥%……&*()——……。
办法总比困难多,既然一定要由用户点击来触发,那么直接把页面里的按钮替换成file控件吧,iframe和form还是动态创建,当用户点击file控件选择文件后,会触发file控件的chang事件,给file控件的change事件绑定ajaxUpload方法并将file控件的id传进去,ajaxUpload方法通过id获取file控件并将file控件appendTo到动态创建的form里,之后的步骤与上面无异——验证格式→提交表单→触发回调。细心的同学会发现,选择文件后,file控件会appendTo到form表单里,那页面里放file控件的地方不是空了么?并且,表单提交后,file会随着form一起被remove掉,所以,在file控件appendTo到form前,先建一个变量P将file控件的父级存起来,form表单提交之后,先将file控件appendTo回到P里面,当然,file控件appendTo到form时,file控件依然会在页面里消失,所以页面里的Btn要保留,把file控件定位在Btn上面,透明度设置成0,这样点击Btn实际上点击的是盖在上面的file控件,这样即使file控件被appendTo到form里面,用户也不会察觉到什么变化,问题迎刃而解!兼容的写法如下:
/*2014年9月19日11:11:07 By 王美建*/functionajaxUpload(opt){/*参数说明:opt.id : 页面里file控件的ID;opt.frameName : iframe的name值;opt.url : 文件要提交到的地址;opt.format : 文件格式,以数组的形式传递,如['jpg','png','gif','bmp'];opt.callBack : 上传成功后回调;*/var iName=opt.frameName; //太长了,变短点variframe,form,file,fileParent;//创建iframe和form表单iframe = $('<iframe name="'+iName+'" />');form= $('<form method="post" style="display:n1one;" target="'+iName+'" action="'+opt.url+'"  name="form_'+iName+'" enctype="multipart/form-data" />');file= $('#'+opt.id); //通过id获取flie控件fileParent = file.parent(); //存父级
file.appendTo(form);//插入body
$(document.body).append(iframe).append(form);//取得所选文件的扩展名var fileFormat=/\.[a-zA-Z]+$/.exec(file.val())[0].substring(1);if(opt.format.join('-').indexOf(fileFormat)!=-1){form.submit();//格式通过验证后提交表单;}else{file.appendTo(fileParent);//将file控件放回到页面
iframe.remove();form.remove();alert('文件格式错误,请重新选择!');};//文件提交完后iframe.load(function(){var data = $(this).contents().find('body').html();        file.appendTo(fileParent);iframe.remove();form.remove();opt.callBack(data);})
}

国际惯例,到这里,方法已经接近完美了,为什么是接近?来看一张图片:

结构代码:
.fileInput{ position: absolute;left: 0;top: 0;height: 30px; filter:alpha(opacity=60);opacity:0.6; background-color: transparent;}
.btn{width: 200px;height: 30px; margin: 100px auto; background-color: yellow; text-align: center; line-height: 30px; overflow: hidden; display: block; position: relative;}<divclass="btn">选择文件<inputtype="file"class="fileInput"name="fileInput"></div>

这就是放在页面里的file控件,外面用一个div包住,在IE10及以下浏览器中,用户单击红色框部分是不会弹出文件选择框的,必须单击蓝色部分或双击红色部分才行,要让蓝色部分占满外面的div怎么做到呢?用css设置宽度只会增加红色部分的宽度,这时我们会发现蓝色部分是有字的,对,可以通过设置font-size来使蓝色部分变宽,然后给file控件加上dir="rtl",这会让浏览按钮移到左边,再给.btn加上overflow:hidden,可以发现浏览按钮已经占满整个div了,如下图:

到这里才真正完成了100%,最后,我们还可以给file控件设置accept属性,限制可选文件格式(IE8及以下不支持该属性),别忘了把file控件的透明的改为0。

posted on 2014-09-21 17:44 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/3984766.html

利用iframe无刷新上传文件的坑相关推荐

  1. php 无刷新上传,php 无刷新上传文件的代码

    php 无刷新上传文件. 有兴趣的朋友,可以参考下:php iframe无刷新上传文件的实现代码 . 1.上传页面 复制代码 代码示例: 无刷新上传文件 function startUpload() ...

  2. Sring3MVC页面无刷新上传文件

    Sring3MVC页面无刷新上传文件 首先,这个框架是利用Ajax与Ctroller进行表单提交和数据交互的,但是Ajax是无法支持File上传的,所以在这里我使用了隐藏的Iframe来做文件上传的数 ...

  3. jQuery+php+ajax实现无刷新上传文件功能

    2019独角兽企业重金招聘Python工程师标准>>> jQuery+php+ajax实现无刷新上传文件功能,还带有上传进度条动画效果,支持图片.视频等大文件上传. js代码: &l ...

  4. iframe实现页面无刷新上传文件(PHP)----备忘

    之前做一个文件上传的,由于那段时间写ajax比较多,所以就想利用Ajax来实现,后来发现,Ajax没法实现文件上传, 后来百度之,这里做个备忘. 提示:利用form表单的target属性和iframe ...

  5. ajax页面无刷新上传文件

    最近在研究struts2文件上传,感觉这块无论是做企业网站还是做系统都用的挺多的,尤其是图片上传.但是上传我们又有几种方式,一种是表单提交,一种是ajax无刷新上传. 这次我要介绍的就是struts2 ...

  6. 使用iframe模拟无刷新上传文件。

    最近一直在研究使用AJAX技术上传文件,也找了网上的一些源码,发现基本上都是使用iframe模拟实现的. 其实AJAX是无法实现上传文件的,那么我们该怎么实现既能不刷新当前页面,又能在用户上传文档完毕 ...

  7. ASP.NET 无刷新上传文件

    这些天一直在做一个无刷新的文件上传功能,现在也总算是做好.可以说是是几经波折吧,开始一直想用AJAX的思路去实现,没想到费了很多时间最后还是徒劳!用ADODB.STREAM 应该也是可以把表单的文件P ...

  8. 文件无刷新上传(swfUpload与uploadify)

    文件无刷新上传并获取保存到服务器端的路径 遇到上传文件的问题,结合之前用到过的swfUpload,又找了一个无刷新上传文件的jquery插件uploadify,写篇博客记录一下分别介绍这两个插件的实现 ...

  9. jQuery AJAX 网页无刷新上传示例

    新年礼,提供简单.易套用的 jQuery AJAX 上传示例及代码下载.后台对文件的上传及检查,以 C#/.NET Handler 处理 (可视需要改写成 Java 或 PHP). 有时做一个网站项目 ...

最新文章

  1. 开源网络备份软件bacula(安装bacula)
  2. BlueMind 3.0.17 发布,消息和协作平台
  3. 微信回调接口java返回true_java 微信支付异步回调接口
  4. python基础——变量
  5. PyTorch | 通过torch.normal()创建概率分布的张量 | torch.normal()如何使用?torch.normal()使用方法 | torch.normal()例子
  6. 接口和抽象类有什么区别?
  7. 客户端持久化解决方案: Web SQL
  8. MongoDB中常用的几种数据类型
  9. MySQL 5.7.25 在Windows 7中安装的记录
  10. python网络编程知识_python六十七课——网络编程(基础知识了解)
  11. 0基础入门VTD-实操静态道路建模3
  12. c++ 三点求外接圆圆心 3维实现
  13. 【毕业设计】基于单片机的心率血氧健康监测手表 - 物联网 嵌入式
  14. RxJava 学习笔记(七) --- Filtering 过滤操作
  15. 买马桶哪个牌子的最好?
  16. Android-smart-image-view加载网络图片
  17. chromedriver与chrome浏览器各版本对应下载
  18. mac 触控板手势以及常用快捷键
  19. 用html做个猜字游戏,HTML5 Canvas API制作简单的猜字游戏
  20. 基于LSTM的美国大选的新闻真假分类【NLP 新年开胃菜】

热门文章

  1. SqlServer 中的增删改查语句的语法
  2. C# 位域[flags]
  3. 7月10日王者荣耀服务器维护,王者荣耀7月10日更新维护公告 7.10全部更新内容汇总...
  4. android自动关闭uvc相机服务,android 调用系统相机崩溃的解决方案
  5. python猜数字循环_python-练习实现猜数字的循环
  6. vba 数组赋值_VBA数组与字典解决方案第18讲:VBA中静态数组的定义及创建
  7. none是不是python的保留字_Python主要保留字
  8. 矩阵的乘法通用模板(C++/Java)
  9. java11模块化开发_【JDK 11】关于 Java 模块系统,看这一篇就够了
  10. 独家下载!Java工程师成神必备宝典