在webpy中获取上传状态

时间:2012-01-14 14:01:14

标签: python progress-bar web.py

我正在为我的项目制作一个上传器,我试图避免任何基于闪存的解决方案(我不喜欢flash和移动平台支持的目标)。 整个过程看起来相当简单:我有一个表单,不错的jQuery进度条,我可以通过脚本更新进度条状态来制作带有超时的ajax请求... 如果我按照Webpy cookbook进行,我唯一没有得到的是如何从服务器接收任何信息:已经写了多少字节/块/什么?

1 个答案:

答案 0 :(得分:2)

您可以使用FormData为现代浏览器创建ajax上传器。

$.fn.uploader = function( options ) {
    var defaults = {},
        opts = $.extend( defaults, options ),
        that = $( this ),
        url = that.data( "upload_url" ),
        is_uploading = false;

    function upload( files ) {

        $.get( "/file/blank.html" );

        if ( FormData === undefined ) {
            alert( "Your browser does not support standard HTML5 Drag and Drop" );
            return;
        }        

        var xhr = new XMLHttpRequest(),
            new_element = $( "<li><p>Loading</p><span></span></li>" )
                .appendTo( that ),
            xhr_upload = xhr.upload,
            form = new FormData();

        xhr_upload.addEventListener( "progress", function( e ) {
            if( e.lengthComputable ) {
                var p = Math.round( e.loaded * 100 / e.total );
                new_element.children( "span" ).text( e.loaded == e.total ? "Processing..." : p + "%" );
            }
        }, false);
        xhr_upload.addEventListener( "load", function( e ){}, false);
        xhr_upload.addEventListener( "error", function( error ) { alert( "error: " + error ); }, false);

        xhr.open( "POST", url, true );
        xhr.setRequestHeader( "X-Requested-With", "XMLHttpRequest" );

        xhr.onreadystatechange = function ( e ) {
            if ( xhr.readyState == 4 ) {
                is_uploading = false;
                if( xhr.status == 200 ) {
                    var data = $.parseJSON( e.target.responseText );
                    if ( data.status == 0 ) {
                        new_element
                            .fadeOut(function (){ $( this ).remove(); })
                            .children( "span" ).text( "Upload error!" );
                    } else {
                        that.html( data.html );
                    }
                } else {
                    new_element
                        .fadeOut(function (){ $( this ).remove(); })
                        .children( "span" ).text( "Upload error!" );
                }
            }
        };
        $.each( files, function() {
            form.append( "files", this );
        });
        is_uploading = true;
        xhr.send( form );
    }

    that.bind({
        "dragover": function( e ) {
            var dt = e.originalEvent.dataTransfer;
            if( !dt || is_uploading ) { return; };
            if( $.browser.webkit ) { dt.dropEffect = "copy"; };
            $( this ).addClass( "active" );
            return false;
        },
        "dragleave": function( e ) {
            $( this ).removeClass( "active" );
        },
        "dragenter": function( e ){ return false; },
        "drop": function( e ){
            var dt = e.originalEvent.dataTransfer;
            $( this ).removeClass( "active" );
            if( !dt || !dt.files || is_uploading ) { return; };
            upload( dt.files );
            return false;
        }
    });

    $( document ).bind({
        'dragenter': function( e ) { return false; },
        'dragleave': function( e ) { return false; },
        'dragover': function( e ) {
            var dt = e.originalEvent.dataTransfer;
            if ( !dt ) { return; }
            dt.dropEffect = "none";
            return false;
        }
    });

};

在服务器端,我这样处理:

def POST(self):
    i = web.webapi.rawinput()
    try:
        files = i.files
        if not isinstance(files, list):
            files = [files]
        for f in files:
            if f.filename:
                filetype, encoding = mimetypes.guess_type(f.filename)
                # do smth with f.file
    except KeyError:
        pass
    if web.ctx.env.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
        web.header("Content-Type", "application/json")
        return json.dumps(dict(status=1, html=unicode(render_partial.files(uploaded_files))))
    else:
        raise web.seeother(web.ctx.env.get("HTTP_REFERER", "/"))

否则你可以查看nginx upload progress模块或apache2上传进度模块,uWSGI也有这个功能。