Подтвердить что ты не робот

Загрузка Django Ajax за пределами формы

Я пытаюсь использовать Valum Ajax Upload для загрузки файлов на Django- основанный сайт, который я делаю. В настоящее время я избегаю формы просто потому, что AU отправляет загрузку как полноту данных POST в ajax запрос. Сейчас у меня очень наивный подход к этому:

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

Это отлично работает... на небольших файлах. Я тестировал с помощью PDF файлов, различных другие файлы и до ~ 20 МБ пакета Google Chrome deb, и они все отлично. Однако, если я перехожу к чему-то вроде CD или DVD iso он ужасно бомбит. Часто Django отправляет обратно из памяти ответ. На первый взгляд это имеет смысл, поскольку SimpleUploadedFile загружаемая в память версия классов загрузки. Я не вижу, как использовать TemporaryUploadedFile, потому что он не принимает фактическое содержимое в своем конструктор. В качестве примечания: я бы подумал, доступная оперативная память, она пойдет в виртуальную память, но что угодно.

Итак, мой вопрос: как мне заставить это работать? Есть ли способ лучше читать в файле? Я попытался напрямую прочитать raw_post_data через Python IO (система использует 2.6.5), но FileIO ascii encoder/decoder очевидно, будут жаловаться на персонажей, не относящихся к ascii, при работе с двоичные файлы. Мне не удалось найти информацию об изменении кодер/декодер.

Я бы не прочь передать данные в форму и Django сделать работа по выбору правильного класса загрузки и т.д., но я не могу понять как передать это, потому что что-то вроде

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

не будет работать, потому что POST содержит файл, а не обычный Информация о Django и FILES не существует.

Как я уже сказал, меня не волнует метод решения, просто Я получаю то, что работает! Благодарю!

4b9b3361

Ответ 1

Ну, я нашел два решения, если кому-то интересно.

Первый - это метод Python с чистым 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 )

Он работал над тестированием для небольших файлов (до 20 МБ), но не смог, когда я попробовал его с файлами ISO (~ 600 МБ) или более. Я не пробовал ничего между 20 МБ и 600 МБ, поэтому не уверен, где точка останова. Я скопировал нижнюю часть трассы ниже, я не уверен, в чем заключается коренная проблема в этой ситуации. Казалось, что есть борьба с памятью, но у меня было достаточно оперативной памяти + своп, чтобы держать файл три раза, поэтому не уверен, почему возникла проблема. Не уверен, что использование других форм 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/

Решение, которое работало со всем, что я выбрал, до 2 ГБ файлов, по крайней мере, потребовало 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 )