前言

最近太忙一直没时间认真的写博客(哈哈哈),最近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. PHP set_error_handler() 函数

    定义和用法 set_error_handler() 函数设置用户自定义的错误处理函数. 该函数用于创建运行时期间的用户自己的错误处理方法. 该函数会返回旧的错误处理程序,若失败,则返回 null. 语 ...

  2. [转] linux 下 进程和线程的区别

    1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是C ...

  3. IE9的BUG?jQuery的BUG?

    本文转载自http://big-student.iteye.com/blog/1898213 在IE9和IE10中,当对一个html的样式初始了一个很大的left或者top时,使用jQuery的off ...

  4. 《Effective C++》 阅读小结 (笔记)

    A person who is virtuous is also courteous. "有德者必知礼" 书本介绍:<Effective C++:改善程序与设计的55个具体做 ...

  5. 使用github创建博客

    本文主要介绍以下几个内容: 1.使用githbu创建自己的博客 2.将博客域名映射到自己的域名 3.如果写博客   一.使用github创建自己的博客 具体可参考https://pages.githu ...

  6. C# 配置文件读取与修改(转)

    C# 配置文件读取与修改   配置文件在很多情况下都使用到, 配置文件分为两种 一种是应用程序的配置文件, 一种是web的配置文件. 两种配置文件最大的区别是web的配置文件更新之后会实时更新, 应用 ...

  7. UITableView 小节-备

    UITableView 让列表自动滑动(定位)到某一行 NSIndexPath*scrollIndexPath = [NSIndexPathindexPathForRow:10inSection:0] ...

  8. android 设置背景为空(透明)

    在给控件设置背景时像ps那样的背景透明 在3.0以下可以使用 imageView.setBackgroundResource(android.R.id.empty); 但是这个方法在3.0以上会出现 ...

  9. STL,ATL,WTL的联系与区别

    STL   即   Standard   Template   Library         STL(标准模板库)是惠普实验室开发的一系列软件的统称.它是由Alexander   Stepanov. ...

  10. orientationchange的兼容性

    移动webapp监测屏幕旋转时常用onorientationchange事件,用此事件获取改变后的屏幕尺寸时需要注意: 1. iphone中,可立即获取改变后的屏幕尺寸. 2. android中,获取 ...