前言

最近太忙一直没时间认真的写博客(哈哈哈),最近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. angularjs使用directive实现倒计时按钮

    前不久在做一个彩票的项目时,有一个手动开奖的需求.所以有了这个倒计时按钮.下面分享下具体的代码: 效果: 代码: App.directive('timerBtn', function() { // 倒 ...

  2. 武汉科技大学ACM:1004: 华科版C语言程序设计教程(第二版)习题5.6

    Problem Description 这天老师又给小豪出了一道题目:给你三根长度分别为a,b,c的火柴,让你计算这三跟火柴能组成的三角形的面积. Input 输入每行包括三个数a,b,c. Outp ...

  3. javascript 不用ajax 用 iframe 子域名下做到ajax post数据

    最近在一个项目中遇到了ajax跨域的问题,情况如下.有三个域名分别是 a.xx.com b.xx.com c.xx.com 这三个域名都会用用ajax post方式相互读取数据.文笔不好, 不写了妈蛋 ...

  4. 基于verilog的FPGA编程经验总结(XILINX ISE工具)

    1.用ISE仿真的时候.所用变量一定要初始化. ISE默认初始量为"XXXXX", 而Quarters是默认为"00000"的, 其实实际上, 下到FPGA里后 ...

  5. SSD、高级格式化硬盘,4K,分区,对齐,Ghost能不能用的解释用SSD的都可以看看

    或者以上,建议选择2048,这是Win7分区使用的值,实际对齐大小就为1024K.  4.如何知道是否对齐?  使用工具AS SSD Benchmark(HDTune Pro 4.6目前测的禁绝)   ...

  6. BZOJ 4407 于神之怒加强版

    http://www.lydsy.com/JudgeOnline/problem.php?id=4407 题意: 给下N,M,K.求 思路:  来自:http://blog.csdn.net/ws_y ...

  7. 模糊集合和隶属度函数--AForge.NET框架的使用(一)

    原文:模糊集合和隶属度函数--AForge.NET框架的使用(一) 什么是AForge.NET? AForge.NET是一个为开发人员和研究人员开发的框架,它可以用于计算机视觉,遗传算法,图像处理,神 ...

  8. PowerShell 转码函数 Default->UTF8

    $chs='你好' function converToUft8($str){ $bs=[System.Text.Encoding]::Default.GetBytes($str); $u8Char=[ ...

  9. http协议的各个版本及区别

      这个东西在一篇博文上面看见的,谢谢原博主提供!又学习了...

  10. 【HDOJ】1057 A New Growth Industry

    纯粹的模拟题目. #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 20 # ...