2010-11-16 21 views
11

我正在尝试使用Valum的Ajax Upload来上传我在制作的基于Django- 的网站上的文件上传。目前我正在避免表格,因为 AU将上载作为整个POST数据发送到ajax 请求中。现在我有一个非常幼稚的方法来做到这一点:Django Ajax上载外部表单

upload = SimpleUploadedFile(filename, request.raw_post_data) 
...then I loop through the chunks to write to disk... 

这对于小文件很有用。我已经使用PDF,各种 其他文件以及高达〜20MB的Google Chrome deb包进行了测试,它们都很棒。但是,如果我移动到像CD或DVD iso 类似的东西,它会轰炸。通常Django发回内存不足 响应。从表面上看,这是有道理的,因为SimpleUploadedFile是上传类的内存版本 。我看不到如何使用 TemporaryUploadedFile,因为它没有在其构造函数 中使用实际内容。作为一个方面说明:我想在使用可用的RAM之后,它会去虚拟内存,但无论如何。

所以,我的问题是,我如何得到这个工作?有没有更好的方法 在文件中读取?我尝试通过 直接读取raw_post_data Python的IO(系统使用2.6.5),但FileIO的ascii编码器/解码器 显然会在使用 二进制文件时抱怨非ascii字符。我无法找到有关更改 编码器/解码器的信息。

我不会介意将数据传递到表单,并具有Django中做选择合适的上传类等的 工作,但我不 如何通过它,因为像

upload_form = UploadForm(request.POST, request.FILES) 

将不起作用,因为POST包含文件而不是正常的 Django info和FILES不存在。

正如我所说,我并不担心解决方案的方法,只是我得到了一些有用的东西!谢谢!

回答

9

那么我发现两个解决方案,如果任何人有兴趣。

第一种是纯粹的Python方法,它是适度成功的。

with BufferedReader(BytesIO(request.raw_post_data)) as stream: 
    with BufferedWriter(FileIO("/tmp/foo.bar", "wb")) as destination: 
    foo = stream.read(1024) 
    while foo: 
     destination.write(foo) 
     foo = stream.read(1024) 

它的工作在测试小文件(高达20MB),但是当我用ISO文件(〜600MB)或者更大的文件尝试失败了。我没有尝试20MB和600MB之间的任何东西,所以不确定断点在哪里。我已经复制下面的跟踪底部,我不确定在这种情况下根本问题是什么。似乎与内存斗争,但我有足够的内存+交换三次以上的文件,所以不知道为什么有问题。不确定使用其他形式的Python读/写或不使用缓冲区在这里会有所帮助。

[error] [client 127.0.0.1] File "/usr/local/lib/python2.6 /dist-packages/django/core/handlers/wsgi.py", line 69, in safe_copyfileobj, referer: http://localhost/project/ 
[error] [client 127.0.0.1]  buf = fsrc.read(min(length, size)), referer: http://localhost/project/ 
[error] [client 127.0.0.1] TemplateSyntaxError: Caught IOError while rendering: request data read error, referer: http://localhost/project/ 

这个解决方案与我所提到的一切有关,至少2GB的文件需要Django 1.3。他们添加了类似于文件的支持,以便直接从HttpRequest中读取数据,所以我利用了这一点。

with BufferedWriter(FileIO("/tmp/foo.bar", "wb")) as destination: 
    foo = request.read(1024) 
    while foo: 
    destination.write(foo) 
    foo = request.read(1024) 
+0

我写了一篇博客文章,展示了如何让Ajax Upload与Django 1一起工作。3,其中包括上述解决方案。 http://kuhlit.blogspot.com/2010/12/ajax-uploads-in-django-with-little-help.html – 2010-12-01 19:59:40

+0

感谢@ @ alex-kuhl有什么办法可以将类似文件的支持融入到最新版本的Django(1.2.5)?我担心我会打到依赖地狱升级。 – michela 2011-03-15 08:48:11

+0

我没有任何升级到1.3的问题,所以它可能没有你想象的那么糟糕。我从来没有尝试过在1.2.5中获得类似文件的支持,所以我不确定这是否可以完成,我怀疑不是那么容易。我在上面的第一个代码片段中尝试使用常规的Python功能并避免使用Django。正如我注意到的那样,它确实有效,但对于超过一定大小的文件却失败了。如果你不允许大文件,那么你可以按原样使用代码,否则我相信有一种方法可以解决它以适用于所有情况。可以像使用不同类的文件读/写一样简单。 – 2011-03-16 17:31:33