Ajax 文件上传

常见异步上传方案


  1. 使用第三方控件(Flash,ActiveX, 浏览器插件等)

优点:

  • 交互与可控性好(多文件、进度展示、续传、暂停)
  • 性能好(可使用底层协议通信)

缺点:
+ 需要浏览器安装插件

  1. 使用隐藏的iframe模拟异步上传

优点:

  • 浏览器原生支持,不需要插件
  • 广泛的浏览器兼容性

缺点:

  • 交互差,体验差,上传过程基本不可控
  • 性能差

关键技术点:

  1. form指定target,提交结果定向到隐藏的iframe。
  2. 提交完成后,iframe中页面与主页面通信,通知上传结果及服务端文件信息。

html

    

附件:

script

    // 上传完成后的回调
    function uploadFinished(fileName) {
        addToFlist(fileName);
        loading(false);
    }

    function addToFlist(fname) {
        var temp = ["

", fname, "", "

" ]; $("#flist").append(temp.join("")); } function delFile(fname) { console.log('to delete file: ' + fname); // TODO: 请实现 } function loading(showloading) { if (showloading) { $("#uptxt").show(); } else { $("#uptxt").hide(); } }

node.js

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

    var multipart = require('connect-multiparty');
    var multipartMiddleware = multipart();

    var fs = require('fs');

    router.all('/', function (req, res) {
        res.sendFile('../public/index.html');
    });

    router.post('/upload2', multipartMiddleware, function(req, res) {
        console.log(req.body);
        console.log(req.files);

        // 实际编程时,一般要将临时文件移动到目标位置,之后删除临时文件
        // 课程中为简化操作,直接将临时文件当成目标文件
        var fpath = req.files.myfile.path;
        var fname = fpath.substr(fpath.lastIndexOf('\\') + 1);

        setTimeout(function() {
            var ret = [""];
            res.send(ret.join(""));
        }, 3000);

    });

    module.exports = router;
  1. 使用xhr level 2 纯ajax异步上传

优点:

  • 支持H5的浏览器原生支持,不需要插件
  • 交互性较好

缺点:

  • 受浏览器支持限制

关键过程:

  1. 创建FormData,放入待上传文件

  2. 通过xhr操作将FormData发送到服务器,实现文件上传

  3. 绑定progress、load、error等事件监听传输过程并在页面显示动态交互信息

html

    

附件:

javascript

    function upload() {
        // 1.准备FormData
        var fd = new FormData();
        fd.append("myfile", $("#myfile")[0].files[0]);

        // 创建xhr对象
        var xhr = new XMLHttpRequest();

        // 监听状态,实时响应
        // xhr 和 xhr.upload 都有progress事件,xhr.progress是下载进度,xhr.upload.progress是上传进度
        xhr.upload.onprogress = function(event) {
            if (event.lengthComputable) {
                var percent = Math.round(event.loaded * 100 / event.total);
                console.log('%d%', percent);
                $("#upprog").text(percent);
            }
        };

        // 传输开始事件
        xhr.onloadstart = function(event) {
            console.log('load start');
            $("#upprog").text('开始上传');

            $("#stopbtn").one('click', function() {
               xhr.abort();
                $(this).hide();
            });

            loading(true);
        };

        // ajax过程成功完成事件
        xhr.onload = function(event) {
            console.log('load success');
            $("#upprog").text('上传成功');

            console.log(xhr.responseText);
            var ret = JSON.parse(xhr.responseText);
            addToFlist(ret.fname);
        };

        // ajax过程发生错误事件
        xhr.onerror = function(event) {
            console.log('error');
            $("#upprog").text('发生错误');
        };

        // ajax被取消
        xhr.onabort = function(event) {
            console.log('abort');
            $("#upprog").text('操作被取消');
        };

        // loadend传输结束,不管成功失败都会被触发
        xhr.onloadend = function (event) {
            console.log('load end');
            loading(false);
        };

        // 发起ajax请求传送数据
        xhr.open('POST', '/upload3', true);
        xhr.send(fd);
    }

    function addToFlist(fname) {
        var temp = ["

", fname, "", "

" ]; $("#flist").append(temp.join("")); } function delFile(fname) { console.log('to delete file: ' + fname); // TODO: 请实现 } function loading(showloading) { if (showloading) { $("#uptxt").show(); $("#stopbtn").show(); } else { $("#uptxt").hide(); $("#stopbtn").hide(); } }

node.js

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

    var multipart = require('connect-multiparty');
    var multipartMiddleware = multipart();

    var fs = require('fs');

    router.all('/', function (req, res) {
        res.sendFile('../public/index.html');
    });

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

        // 实际编程时,一般要将临时文件移动到目标位置,之后删除临时文件
        // 课程中为简化操作,直接将临时文件当成目标文件
        var fpath = req.files.myfile.path;
        var fname = fpath.substr(fpath.lastIndexOf('\\') + 1);

        res.json({fname: fname});
    });

    module.exports = router;

你可能感兴趣的:(Ajax 文件上传)