2010-11-16 22 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