前言

最近太忙一直没时间认真的写博客(哈哈哈),最近pm提一个需求,移动端需要一个上传图片的功能,允许多选、删除、预览、点击查看大图并可以滑动。虽然听起来很多,但是这个功能在web上实现过啊,使用webuploader妥妥的,然后就拍着胸口答应了下来,并让B同事做。

开发完成后,后端说同一次上传多张图只能发一次请求,纳尼。。我没仔细看过webuploader的API,不知道为什么需要单独进行上传,看了一下请求信息,在支持FormData的浏览器中使用的FormData来模拟form。那既然这样也可以支持多图一起请求啊(如果webuploader支持或者有其他考虑,欢迎大家指出),算了,自己造吧,也就有了这篇随笔。

1.form表单提交

像我这样的小白都知道form表单提交之后要刷新页面,更别说要实现pm提的那些需求了,但是代码还是要上一下的。

<form action="http://baidu.com" target="" id="uploadForm" enctype="multipart/form-data">
  <input id="file" type="file" name="file"/>
  <input type="submit" name="submit" id="submit" value="upload" />
</form>

因为我们这里要上传文件,所以enctype的值为multipart/form-data。

2.form+iframe

看到上面的代码,form有一个target的属性,规定在何处打开action,可能的值有

  • _blank
  • _self
  • _parent
  • _top
  • framename

就不一一介绍了,我们最关心的是最后一个值,framename,我们将页面放在iframe里处理就不担心刷新的问题了,然后再设置一个回调就可以处理服务端返回的参数

html:

<form action="http://baidu.com"  target="" id="uploadForm" enctype="multipart/form-data">
<input id="file" type="file" name="file"/>
<input type="submit" name="submit" id="submit" value="upload" />
</form>

jq:

<script type="text/javascript">
var form = $("#uploadForm");
form.on("submit",function(){
var seed = Math.floor(Math.random()*1000),
id = "uploader-iframe" + seed,
callback = "uploader-cb" + seed,
iframe = $("<iframe id='"+id+"' name='"+id+"' style='display:none'></iframe>"),
url = form.attr("action");
form.attr("target",id).append(iframe).attr("action",url+"?iframe="+callback);
window[callback]=function(data){
iframe.remove();
form.removeAttr("target");
form.attr("action",url);
window[callback] = undefined;
}
})
</script>

有没有觉得和jsonp的方式有点像,但是这里不需要动态创建script标签来调用,因为iframe本来就是一个页面,只需要服务端返回调用方法和数据在iframe页面就ok了

服务端返回:

<script type="text/javascript">
window.top.window[callback](data)
</script>

callback是我们事前约定好并传给服务器的参数,data为服务器返回的数据。

还有一种拿数据的方法,不通过后端回调

iframe.on("load",function(){
var ifr =$(this).contents() //jq对象document
//ifr = this.contentDocument || this.document//兼容ie
})

跟后端约定返回数据格式,然后进行操作

form+iframe这种伪异步的提交方式对文件的处理还是无力,不能想删就删,预览图片只有先传给后台,后台再返回一个线上的地址

3.HTML5之FormData、FileReader

当当当。。文章的主角出现

利用FormData模拟表单数据,通过ajax进行提交,FileReader的readAsDataURL方法拿到base64地址来预览(完美,注意兼容性)

form表单初始化FormData提交

<form action="http://baidu.com"  target="" id="uploadForm" enctype="multipart/form-data">
<input id="file" type="file" name="file"/>
<input type="submit" name="submit" id="submit" value="upload" />
</form>
$.ajax({
url: '/upload',
type: 'POST',
cache: false,
data: new FormData($('#uploadForm')[0]),
processData: false,
contentType: false
}).done(function(res) {
}).fail(function(res) {});
  • processData设置为false。因为data值是FormData对象,不需要对数据做处理。
  • <form>标签添加enctype="multipart/form-data"属性。
  • cache设置为false,上传文件不需要缓存。
  • contentType设置为false。因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。

上传后服务端通过file来接收文件流。

通过FormData对象append方法来添加

<div id="uploadForm">
<input id="file" type="file"/>
<button id="upload" type="button">upload</button>
</div>
var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
$.ajax({
url: '/upload',
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false
}).done(function(res) {
}).fail(function(res) {});

FileReader获取DataUrl

<input multiple="multiple" id="file" type="file" name="file"/>
var reader = new FileReader();
reader.onload=function(e){
//e.target.result为$("#file")[0].files[0]的base64地址
}
reader.readAsDataURL($("#file")[0].files[0])

更多FormData和FileReader方法可以去查看一下API

4.flash实现

flash的实现不在我们讨论的范围,而且浏览器的支持对flash有很大的影响,现在有很多上传组件做了低版本flash的兼容。比如webuploader、uploadify等

需求实现

说了这么多,最后还是要回归到需求上来,由于这个需求是在移动端上,我们自然而然就选了第三种实现方式,这里讲一下实现的思路(伪代码)。

var formdata = new FormData(), count = 0, mId = '${model.id}', a = [];
formdata.append("id", mId)
$("#file").on("change",function() {//file触发change时循环files做相应的处理
if ($("#file")[0].files.length > 0) { for (var i = 0, j = $("#file")[0].files.length; i < j; i += 1) { (function(k) {//按顺序插入预览图片,并在数组中保存对应的files
var reader = new FileReader()
reader.onload = function(e) {//保证预览顺序和files数组顺序一致,方便后面删除file
count += 1;
a.push($("#file")[0].files[k]);
$(".filelist").append("<li><p class='imgWrap'><img class='close' src='img/close.png'/><img id='"
+ $("#file")[0].files[k].name
+ "' class='choose-img' src='"
+ e.target.result
+ "'' /></p></li>");//预览相关处理
$(".swiper-wrapper").append("<div class='swiper-slide'><img id='"
+ $("#file")[0].files[k].name
+ "' class='choose-img' src='"
+ e.target.result
+ "'' /></div>");//点击查看大图相关处理
} reader.readAsDataURL($("#file")[0].files[i]);
})(i); } }
});
$(document).on("click", ".close", function() {//图片删除处理,处理files数组,更新count
var $this = $(this);
a.splice($this.parents("li").index(), 1);
$(".swiper-slide").eq($this.parents("li").index()).remove();//如果考虑复用,这个index可以优化下
count -= 1;
$this.parents("li").remove();
$("#jsUpload").show();
})
$("#jsUploadBtn").on("click", function() {//上传时,将files数组循环append进FromData进行ajax提交
for (var i = 0, j = a.length; i < j; i += 1) {
formdata.append("file", a[i])
}
$.ajax({
url : '',
type : 'POST',
cache : false,
data : formdata,
processData : false,
contentType : false
}).done(function(data) {
if (data == 'error') {
$(".flie-toast").addClass("hide");
toast("上传失败,请联系管理员!");
} else if (data == 'no') {
$(".flie-toast").addClass("hide");
toast("您没有参与比赛,不允许上传截图");
} else if (data == 'yes') {
$(".flie-toast").addClass("hide");
toast("上传成功");
setTimeout(function() {
window.location.href = "";
}, 2000);
} else {
$(".flie-toast").addClass("hide");
toast("上传失败,请联系管理员!");
} }).fail(function(res) {
}); })

虽然FormData对象有一个delete的方法,但是现在浏览器的支持率堪忧啊,所以只有曲线救国了。

个人知识的宽度和广度毕竟有限,如文章有什么疏漏和错误的地方,欢迎大家留言指出。

web前端之文件上传的更多相关文章

  1. 基于 java 【Web安全】文件上传漏洞及目录遍历攻击

    前言:web安全之文件上传漏洞,顺带讲一下目录遍历攻击.本文基于 java 写了一个示例. 原理 在上网的过程中,我们经常会将一些如图片.压缩包之类的文件上传到远端服务器进行保存.文件上传攻击指的是恶 ...

  2. JAVA Web 之 struts2文件上传下载演示(二)(转)

    JAVA Web 之 struts2文件上传下载演示(二) 一.文件上传演示 详细查看本人的另一篇博客 http://titanseason.iteye.com/blog/1489397 二.文件下载 ...

  3. JAVA Web 之 struts2文件上传下载演示(一)(转)

    JAVA Web 之 struts2文件上传下载演示(一) 一.文件上传演示 1.需要的jar包 大多数的jar包都是struts里面的,大家把jar包直接复制到WebContent/WEB-INF/ ...

  4. FormData使用方法详解,以及在IE9环境下,前端的文件上传问题

    FormData的主要用途有两个: 1.将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率. 2.异步上传文件 一.创建formData对象 ...

  5. 构建web应用之——文件上传

    我们通过使用multipart请求数据接收和处理二进制信息(如文件).DispatcherServlet并没有实现任何解析multipart请求数据的功能,它将该任务委托给了Spring中的multi ...

  6. web实现大文件上传分片上传断点续传

    需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端修改 由于项目使用的是 ...

  7. WEB安全性测试之文件上传漏洞

    1.漏洞描述:文件上传漏洞,是指可以利用WEB上传一些特定的文件包含特定代码如(<?php phpnfo;?> 可以用于读取服务器配置信息.上传成功后可以点击) 上传漏洞是指用户上传了一个 ...

  8. WEB安全:文件上传漏洞

    文件上传漏洞过程 用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力. 一般的情况有: 上传文件WEB脚本语言,服务器的WEB容器解释并执行了用户上传的脚本,导致代码执行: ...

  9. IIS 之 通过 Web.config 修改文件上传大小限制设置方法

    在IIS 6.0中,不设置默认大小为4M,设置文件上传大小的方法,maxRequestLength(KB),executionTimeout(毫秒),配置如下节点: <system.web> ...

随机推荐

  1. C# 操作电脑 关机 重启 注销 休止 休眠

    // 关机 强制电脑10秒之内关机 //System.Diagnostics.Process.Start("shutdown", "-s -f -t 10"); ...

  2. (六)Angularjs - 启动引导

    自动引导 AngularJs 通过 ng-app 指令进行自动引导 手工引导启动框架 如果一个HTML文件中 有多个ng-app,AngularJS只会自动引导启动它找到的第一个ng-app应用,这是 ...

  3. 逆天的IE7中,绝对定位元素之间的遮盖问题

    个人比较支持IE9以上的版本,认为他们的样式和效果都是比较人性化的,不过很多时候还是不得不考虑其他版本浏览器的感受,这里IE6就不用考虑他了,这货简直就是IT史上的奇葩,这里要说一个IE7的绝对定位和 ...

  4. iBox v2.0 发布,Web化仿iOS7界面/交互的JavaScirpt库

    iBox2 是一个仿 iOS 7 界面/交互的 JavaScirpt 库,它运行在 webkit 内核的移动浏览器之上,依赖 iScroll5,帮助开发者构建更接近 iOS 体验的 WebApp. 伴 ...

  5. python_基本语法_01

    离毕业工作还有几个月,本来想早点去公司实习,无奈gb学校不给放.好吧,既然这样,就学门语言. 参考与 http://www.cnblogs.com/vamei ,我是跟着这位博客牛人的博客教程学的,具 ...

  6. Windows10 删除已经保存的WIFI热点

    自己的笔记本很多时候都是连接WIFI上网,导致保存的WIFI越来越多,有些都过期不能用了,但还是在列表中存在着,致使列表很长很难看,如下: 删除无用热点的方法如下: win+r运行cmd,进入命令行界 ...

  7. JAVA三大框架SSH的各自作用

        一.Spring Spring是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯. Spring的 ...

  8. awk的思维导图

  9. 『电脑技巧』破解Win7/Win8登录密码

    Pic via baidu 0x 00 破解思路 用户的明文密码经过单向Hash加密生成Hash散列,Hash散列又被加密存放在系统盘\Windiws\System32\config文件下 要获得明文 ...

  10. [布局]bootstrap基本标签总结2

    缩略图 <div class="container"> <div class="row"> <div class="co ...