资讯专栏INFORMATION COLUMN

web端文件上传功能的思考

Jaden / 652人阅读

摘要:概述文件上传是一个很常见的需求,实现文件上传的技术也很多。帮助文档模拟无刷新的文件上传功能页面无刷新上传文件模拟,超简单为什么上传文件的表单里要加个属性接口对象的介绍使用对象涉及文章侵权,请邮件告知。

概述

文件上传是一个很常见的需求,实现文件上传的技术也很多。下面就谈谈一些常见的上传技术以及它们的优劣。

传统表单上传

传统表单文件上传估计是运用最广泛和最简单的技术了,说它简单是因为只要指定表单的enctypemultipart/form-data,就行了。简单可靠所以被运用的广泛。传统表单上传示例如下所示:

表单中的action参数指的是后台处理上传文件的接口。target参数规定了规定在何处打开 action URL,常见的参数有_blank、_self、__top或者指定的iframe。method参数规定了表单提交的方式,这里只能使用**post**方式提交,而不能用**get**方式。最后enctype的参数规定了在发送到服务器之前应该如何对表单数据进行编码方式,常见的参数有**application/x-www-form-urlencoded**、**text/plain**和示例中的**multipart/form-data**,因为上传的文件都是非纯文本传输,所以指定的类型必须只能是**multipart/form-data**。

这种方式的局限性是不能批量处理,而且表单上传是同步的,表单已提交,页面就会刷新。

第三方插件处理文件上传

如果你想实现异步提交文件,且可以进行批量处理文件,那么只能通过第三方插件来实现了,第三方插件实现技术有很多,比如Flash、java applet、ActiveX等技术,其中Flash技术是运用最广泛、最成熟的一种方案。

不过第三方插件已经不属于前端开发范围了,所以不会详细细说。不过到时可以我常用的FLash上传插件有SWFupload、uploadfile、百度的webupload等。

第三方插件的好处是能做批量处理、异步提交。缺点也是显而易见的是要浏览器支持。

模拟异步上传文件

说到异步,可能有人会说,能不能通过ajax来实现文件的异步上传呢?想法很美好,现实却很残酷,ajax与后端通信 只能传送字符串,是无法传递实体文件的,所以用ajax是无法实现直接文件上传的。不过我们却可以在页面“埋”一个隐藏iframe来模拟文本的异步提交。

具体的原理是,在点击提交按钮时,动态的生成一个隐藏iframe加入到页面上,并且 将form 的 target指向该隐藏iframe,服务端就接收到上传的file文件,并进行相应的操作,然后将返回结果返回到隐藏的iframe里面,这时我们可以与后端开发约定返回结果的格式,可以是json格式,便于我们前端操作,然后前端部分就可以用iframe.contentWindow.document.body.innerHTML来获取后端返回的结果,进行相应的parseJSON处理,即可像处理ajax返回的json一样,处理数据。

示例代码如下所示:

/**
 * 模拟ajax无刷新文件上传
 */
var fileUpLoad = function(config) {

    var ifr = null,
        fm = null,
        defConfig = {
            submitBtn: $("#J_submit"), //提交按钮
            complete: function(response) {}, //上传成功后回调
            beforeUpLoad: function() {}, //点击提交未上传时回调
            afterUpLoad: function() {} //点击提交上传后回调
        };

    //静态变量
    var IFRAME_NAME = "fileUpLoadIframe";

    //配置
    config = $.extend(defConfig, config);

    //绑定submit事件
    config.submitBtn.bind("click", function(e){
        e.preventDefault();

        //点击提交前触发事件, 函数返回false可阻止提交表单,用于file为空判断
        if (config.beforeUpLoad.call(this) === false) {
            return;
        }

        //生成一个隐藏iframe,并设置form的target为该iframe,模拟ajax效果
        ifr = $("");
        fm = this.form;

        ifr.appendTo($("body"));
        fm.target = IFRAME_NAME; //target目标设为ifr

        //上传完毕iframe onload事件
        ifr.load(function(){
            var response = this.contentWindow.document.body.innerHTML;

            config.complete.call(this, response);
            ifr.remove();
            ifr = null; //清除引用
        });

        fm.submit(); //提交表单

        //点击提交后触发事件
        config.afterUpLoad.call(this);

    });

};

调用方式如下:

   fileUpLoad({
    submitBtn: $("#J_submit"),
    complete: function(response){ //上传成功后处理回调
        var d = $.parseJSON(response);

        alert("返回成功")
        console.log(d);
    },
    beforeUpLoad: function() {
        alert("上传前");
    },
    afterUpLoad: function() {
        alert("上传后");
    }
}); 

这种方式的好处是,虽然不是异步提交,但是给人的感觉好像是通过异步方式上传了文件。缺点是依然不能进行批量处理文件。

使用FormData对象发送文件

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.其兼容性如下所示:

有图可知,这个接口兼容性在IE上表现的并不是很好,最新只支持IE10+,不过IE10+的市场份额现在还不是很多,如果你考虑兼容性的话,建议不要使用这个接口。

那怎样通过FormData上传文件呢。可以参考下面的代码。
html结构:



Stash the file!

脚本代码:

function sendForm() {
  var oOutput = document.getElementById("output");
  var oData = new FormData(document.forms.namedItem("fileinfo"));

  oData.append("CustomField", "This is some extra data");

  var oReq = new XMLHttpRequest();
  oReq.open("POST", "stash.php", true);
  oReq.onload = function(oEvent) {
    if (oReq.status == 200) {
      oOutput.innerHTML = "Uploaded!";
    } else {
      oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.
"; } }; oReq.send(oData); }

这个属性弥补了ajax1不能异步上传文件的不足。

帮助文档

模拟AJAX无刷新的文件上传功能
页面无刷新ajax上传文件--模拟iframe,超简单
为什么上传文件的表单里要加个属性enctype
FormData接口对象的介绍
使用FormData对象

ps:涉及文章侵权,请邮件告知。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87672.html

相关文章

  • 服务器文件分片合并思考和实践

    摘要:原文服务器端文件分片合并的思考和实践笔者在项目中处理大文件上传的需求,仿照七牛云存储的接口设计。然而,在服务器端文件合并时遇到了很大的问题合并太慢。服务器端的分片合并现在进入本文的重点。 原文:服务器端文件分片合并的思考和实践 笔者在项目中处理大文件上传的需求,仿照七牛云存储的接口设计。然而,在服务器端文件合并时遇到了很大的问题:合并太慢。本文记录了当时的思路和解决的方案 大文件的...

    huaixiaoz 评论0 收藏0
  • 浅析前上传

    摘要:项目上也用到很多上传文件的地方,七牛云,阿里云,讯飞上传都接触过,所以在这里做一个记录,总结一下前端上传的几种方式。类型的文件名七牛云上传浅析是一个基于七牛开发的前端。 showImg(https://segmentfault.com/img/bVbvibu?w=1920&h=1080); 图片,音频,视频等等这几种常见的资源类型,如果需要从前端上传到服务端,有几种方式呢?不妨回顾一下...

    terro 评论0 收藏0
  • 2016年总结--成长

    摘要:马尔代夫之行重头戏这一年的工作情况这一年,个人感觉还是做了不少事情,主要集中在我们公司的前端领域,同时也给整个技术团队不少的建议,引入了不少新的东西和方式,总结起来比较重要的在下面五个方面。 如果想看技术相关的,下拉到后面的重头戏就是了。 一个活动页面 在15年末的时候,加入到罗辑思维,刚过来就接手了一个微信朋友圈要传播的活动页面,效果页面大概和当时锤子手机的活动页面漂亮的不像实力派类...

    niuxiaowei111 评论0 收藏0

发表评论

0条评论

Jaden

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<