mootools无刷新上传文件(图片)插件

无刷新上传的方法很多,比如:

  1. 利用现代浏览器的FormData。
  2. 利用现代浏览器的FileReader将图片文件编程base64编码。
  3. 利用类库(如jQuery)的ajax。
  4. 利用iframe。

最近接到一个项目要求兼容IE8+,没有选择余地,只能用iframe了。原理如下:

<form action="upload.php" target="iframe" method="post" entype="mutipart/form-data">
  <input type="file" name="file"/>
  <iframe name="iframe" class="hide">
  </iframe>
</form>

这上述代码里,最重要得就是** target="file" **。它实现了使用隐藏的iframe上传文件。
这样,我们就可以在上传文件后返回给iframe结果,再用js解析iframe里的内容--或者是显示图片,或者是显示提示信息。

代码如下:

/**
 * 利用隐藏iframe无刷新上传图片
 * usage:
 * var widget = new IframeUpload({
        container:'.container',//上传的组件(带+号的div)要放在哪个类或者id里,隐藏的input也放在这里
        uploadUrl:'upload.php',
        deleteUrl:'delete.php',
        deleteMethod:'post',//可以不写,默认是post
        max:5//最多上传几张图片
    });
 * @type {Class}
 */
var IframeUpload = new Class({
    count:0,//记录目前页面上存在的iframe
    initialize:function(options){
        var othis = this;
        var defaultOptions = {
            container:"file",
            marginRight:10,//upload widget 间隔
            className:'iframe-upload-widget',//给adopt进页面的form加一个类,最后删除
            max:5,
            interval:50,
            ajaxName:'file',//iframe 上传图片时,图片的name
            imageName:'file[]',//最后一次性上传图片时图片的name
            uploadUrl:"upload.php",
            method:'post',//upload method
            deleteUrl:'',
            deleteMethod:'post',
            deleteTag:'id',//删除一张图片时,指定隐藏input的name
            enctype:"multipart/form-data",
            onSuccess:function(html){
                //console.log(html)
                // var othis = this.self;
                var arr = html.split(";");
                if(arr.length == 2){
                    this.appendImage(arr[0]);
                    this.setValue(arr[1]);
                }else{
                    Dialog.alert(html);
                }
            }
        };

        if(typeOf(options) == "object"){
            var opt = this.opt = Object.merge(defaultOptions,options);
        }else{
            var opt = this.opt = defaultOptions;
        }
        var classOrId = opt.container;
        var first = classOrId.substring(0,1);
        if(first == "."){
            othis.container = $$(classOrId);
        }else if(first == "#"){
            alert("container can not start with #");
        }else{
            othis.container = $(classOrId);
        }
        othis.init();
    },
    init:function(){
        this.createInput();
    },
    clear:function(){
        var othis = this;
        $$("."+othis.opt.className).dispose();
    },
    getIframeBody:function(iframe){
        return iframe.contentWindow.document.body;
    },
    listen:function(iframe,input,wrap,tagIdInput){
        var othis = this;
        var opt = othis.opt;

        var timeout = setInterval(function(){
            var html = othis.getIframeBody(iframe).innerHTML.trim();
            if(html != ""){
                othis.getIframeBody(iframe).innerHTML = "";
                clearInterval(timeout);
                if(othis.count < opt.max){
                    othis.createInput();
                }
                opt.onSuccess.bind({
                    self:othis,
                    setValue:function(value){
                        input.set("value",value);
                        tagIdInput.set("value",value);
                    },
                    appendImage:function(imageUrl){
                        othis.appendImage(wrap,imageUrl);
                    },
                    input:input,
                    tagInput:tagIdInput,
                    div:wrap
                })(html);
            }
        },opt.interval);
    },
    uuid:function(num){
        var letters = ['a','b','c','d','e','f','g','h','i','1','2','3','4','5','6','7','8','9'];
        if(typeOf(num) != "number"){
            num = 8;
        }
        var code = "";
        for(var i = 0;i<num;i++){
            code += letters.getRandom();
        }
        return code;
    },
    appendImage:function(wrap,imageUrl){
        wrap.setStyle("background-image","url("+imageUrl+")");
    },
    createInput:function(){
        var othis = this;
        var opt = othis.opt;
        othis.count ++;
        var iframeName = othis.uuid();
        var mapId = othis.uuid();//upload div 上绑定mapId,通过这个id找到对应的隐藏input

        var wrap,form,input,iframe,tagIdInput,hiddenInput;

        input = new Element("input",{
            type:'file',
            name:opt.ajaxName,
            events:{
                'change':function(){
                    form.submit();
                    othis.listen(iframe,hiddenInput,wrap,tagIdInput);
                }
            }
        });

        wrap = new Element("div",{
            'data-mapid':mapId,
            styles:{
                width:70,
                height:70,
                marginRight:opt.marginRight,
                position:'relative',
                display:'inline-block',
                backgroundColor:"#efefef",
                color:"#ddd",
                border:'1px solid #ddd',
                textAlign:'center',
                fontSize:13,
                backgroundRepeat:'no-repeat',
                backgroundSize:'contain',
                backgroundPosition:'center'
            },
            html:"<span style='font-size:25px'>+</span><p style='margin-top:10px'>上传图片</p>",
            events:{
                'click':function(){
                    input.click();
                },
            },
        });

        form = new Element("form",{
            action:opt.uploadUrl,
            method:opt.method,
            target:iframeName,
            enctype:opt.enctype,
            'class':opt.className,
            styles:{
                display:"none"
            }
        });

        iframe = new Element("iframe",{
            name:iframeName,
            styles:{
                display:'none'
            }
        });

        tagIdInput = new Element("input",{
            name:opt.deleteTag,
            styles:{
                display:'none',
            }
        });

        //用于最后上传的input
        hiddenInput = new Element("input",{
            type:'hidden',
            'data-index':1,
            id:mapId,
            name:opt.imageName,
        });

        if(othis.count > 1){
            var deleteIcon = new Element("span",{
                styles:{
                    position:"absolute",
                    right:-8,
                    top:-8,
                    borderRadius:'50%',
                    textAlign:'center',
                    lineHeight:18,
                    width:16,
                    height:16,
                    border:'1px solid #333',
                    backgroundColor:'#efefef',
                    color:'red',
                    cursor:'pointer',
                },
                html:'×',
                events:{
                    click:function(e){
                        e.stop();
                        if(opt.deleteUrl){
                            var data = opt.deleteTag+"="+hiddenInput.get("value");
                            new Request({
                                url:opt.deleteUrl,
                                'data':data,
                                method:opt.deleteMethod
                            }).send();
                        }
                        hiddenInput.dispose();
                        wrap.dispose();
                        othis.count --;
                    }
                }
            });
            wrap.adopt(deleteIcon);
        }

        form.adopt(input,iframe,tagIdInput);
        $$(document.body).adopt(form);

        othis.container.adopt(wrap,hiddenInput);
    },
});

后端php对应的代码:

#file upload.php
<?php
$file = $_FILES;
$f = $file['file'];
move_file_upload($f['tmp_name'],"test.jpg");
$id = uniqid();
echo "http://localhost/test.jpg;".$id;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容