Ajax实现文件异步上传

2 篇文章 0 订阅

总结自极客学院ajax文件上传地址

一、异步上传的概念

所谓异步上传,就是对比传统的表单提交,实现一种页面局部刷新的功能。
传统的表单提交一般都是点击某个提交按钮,然后真个页面处于一种被锁定的状态,上传完成后,页面跳转到一个新的页面。而一部上传则是在整个上传过程中,页面都没有被阻塞,用户可以同时进行其他的交互操作,在上传完成后,在局部页面中给出提示信息,不对整个页面进行刷新。

二、异步上传的实现方式

1.iframe实现伪异步上传

关键操作:

  • 提交表单的时候,定义一个target属性,指向一个隐藏的iframe
  • 文件上传完成后,iframe返回信息给当前主页面,使其能对文件进行相关的后续操作
<iframe name="ifm" style="display: none;"></iframe>
<!-- 定义一个隐藏的iframe,给它定义一个name属性,为后续target指定目标页面 -->
<form action="/upload" enctype="multipart/form-data" method="post" target="ifm" onsubmit="loading(true)">
<label for="myfile">附件:</label>
<input type="file" name="myfile" id="myfile" />
<input type="submit" class="btn btn-primary" value="异步上传" />
<span id="uptxt" style="display: none;">正在上传。。。</span>
</form>
 <div id="flist" style="border:1px dotted darkgray;"></div>
 <!-- 来存放上传的文件列表 -->
  <script>
        function uploadFinished(fileName) {
            addToList(fileName);
            loading(false);
        }
        function addToFlist(fname) {
            var temp = ["<p id='" + fname + "'>",fname, "</p>"];
            $("#flist").append(temp.join(""));
        }

        function loading(showloading) {
            if (showloading) {
                $("#uptxt").show();
            } else {
                $("#uptxt").hide();
            }
        }

    </script>

表单提交的时候,信息被提交到那个target指向的隐藏的iframe页面中,使得当前主页面不刷新,而普通的文件上传中,target为当前主页面,所以文件上传成功后,返回的信息就显示在了当前页面,使得页面被刷新。
提交表单后,iframe会给当前页面反馈一些信息,来提示当前的上传进度。

后端代码处理

var express = require('express');
var router = express.Router();

var multipart = require('connect-multiparty');    //加载中间件
var multipartMiddleWare = multipart();    //调用中间件的构造方法
var fs = require('fs');

router.post('/upload',multipartMiddleWare,function(req,res) {
    //第一个参数:被请求资源的url,第二个参数:中间件对象,第三个参数:异步文件上传处理函数
    var fpath = req.files.myfile.path;
    var fileName = fpath.substr(fpath.lastIndexOf('\\') + 1);    //获取临时文件的名称,返回给当前页面

    setTimeout(function() {
        var ret = ["<script","window.parent.uploadFinished('" + fileName + "');","</script"];

        res.send(ret.join(""));
    },1000)
});

上传完成后,iframe要通知当前提交页面上传完成,并传递上传的文件名称,以便当前页面做一些后续的处理
iframe页面返回的时候,直接执行一段脚本。找到主页面即window.parent,调用这页面定义的一个函数,参数为当前上传的文件名称

2.xhr level2实现真正意义的异步上传

关键操作:
创建formData对象,将要上传的文件放入formData中
创建xhr对象,发送请求
(formData是HTML5的一个新属性,类似于传统的表单,formData中可以加入各个表单项以及它们的值。)

<div class="container">
        <div class="roe">
            <div class="col-md-12">
                <div>
                   <div class="input-group">
                       <label for="myfile">附件:</label>
                       <input type="file" id="myfile" />
                   </div>
                    <div>
                        <input type="button" class="btn btn-primary" onclick="upload()" value="异步上传" />
                        <span id="uptxt" style="display: none;">正在上传...</span>
                        <span id="upprogress"></span>
                        <button id="stop" class="btn btn-danger" style="display: none;">取消上传</button>
                    </div>
                </div>

                <div id="fileList" style="border: 1px dotted darkgray"></div>
            </div>
        </div>
    </div>
 <script>
   var formdata = new FormData();    //创建一个formData对象
   formdata.append('myfile',$('#myfile')[0].files[0]);
    //创建xhr,然后初始化对象,将请求发送出去
            var xhr = new XMLHttpRequest();
        function upload() {
            //创建formData对象,然后将我们想要上传的文件放到formData里
            var xhr = new XMLHttpRequest();

            //监听状态,实时响应
            xhr.upload.onprogress = function(event) {      
                if(event.lengthComputable) {     
                    var percent = Math.round(event.loaded * 100 / event.total);  
                    console.log('%d%',percent);
                    $('#upprogress').text(percent);
                }
            };

            //传输事件开始,当xhr对象执行了send之后,马上会触发这个事件
            xhr.onloadstart = function(event) {
                console.log('load start');
                $('#upprogress').text('开始上传');
                $('#stop').one('click',function() {      //显示‘取消盛传’按钮
                    xhr.abort();       //取消事件
                    $(this).hide();   //隐藏取消按钮
                });
                loading(true);
            };

            //文件上传成功
            xhr.onload = function(event) {
                console.log('upload success');
                $('#upprogress').text('上传成功');
                console.log(xhr.responseText);
                var ret = JSON.parse(xhr.responseText);   //两返回的数据转换为json格式
                addToList(ret.fname);   //将文件名显示在文件列表
            };

            //文件上传失败
            xhr.onerror = function(event) {
                console.log('error');
                $('#upprogress').text('上传失败');
            };

            //上传被取消
            xhr.onabort = function(event) {
                $('#upprogress').text('上传取消');
            };

            xhr.onloadend = function(event) {
               console.log('load end');
                loading(false);
            };

            xhr.open('POST','/upload3',true);
            xhr.send(formdata);
        }

        function addToList(fname) {
            var temp = ["<p id='" + fname + "'>",fname,"</p>"];
            $('#fileList').append(temp.join(""));
        }

        function loading(showloading) {
            if(showloading) {
                $('#uptxt').show();
                $('#stop').show();
            }else {
                $('#uptxt').hide();
                $('#stop').hide();
            }
        }
    </script>
  • 在这里,没有借助form表单,而采用直接创建formData对象,然后添加数据的方法。在传统的页面中放一个文件域,在选择文件后,将文件信息放进formData对象中。
  • 通过append方法将表单项加载进formData对象中。
    第一个参数为表单项的名字,相当于input的name属性。
    第二个参数为要传入的内容。
  • onprogress是下载事件,而upload.onprogress则是上传事件
  • event.lengthComputable:如果文件长度可计算(若文件太小或者在传输前没有捕获到文件的真实长度时,则该值为false)
  • 计算上传进度。event.loaded表示已经传输完成的大小,event.total表示当前上传文件的大小

后端代码处理

router.post('/upload3',multipartMiddleWare,function(req,res) {
    console.log(req.files);

    var fpath = req.files.myfile.path;
    var fname = fpath.substr(fpath.lastIndexOf('\\') + 1);
    res.json({fname: fname});
});
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值