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