web前端之文件上传

来源:互联网 发布:启明星辰网络安全设备 编辑:程序博客网 时间:2024/05/22 17:50

发完成后,后端说同一次上传多张图只能发一次请求,纳尼。。我没仔细看过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的方法,但是现在浏览器的支持率堪忧啊,所以只有曲线救国了。

原创粉丝点击