Ответ 1
Django 1.3 является приемлемым. Так что я могу либо сделать что-то с request.raw_post_data или request.read() (или, альтернативно, некоторые другой лучший способ доступа). Любые идеи?
Вы не хотите прикасаться к request.raw_post_data
- это означает чтение всего тела запроса в память, что, если вы говорите о загрузке файлов, может быть очень большой, поэтому request.read()
- это способ пойти, Вы можете сделать это с помощью Django <= 1.2, но это означает, что нужно выполнить поиск в HttpRequest
, чтобы выяснить правильный способ использования частных интерфейсов, и это реальное перетаскивание, чтобы затем обеспечить, чтобы ваш код также был совместим с Django >= 1.3.
Я бы предположил, что вы хотите сделать репликацию существующих частей поведения загрузки файлов в классе MultiPartParser
:
- Извлеките загрузчиков из
request.upload_handlers
(которые по умолчанию будутMemoryFileUploadHandler
иTemporaryFileUploadHandler
) - Определите длину содержимого запроса (поиск длины контента в
HttpRequest
илиMultiPartParser
, чтобы увидеть правильный способ сделать это.) - Определите имя загруженного файла, либо указав его клиенту с использованием последней части пути URL-адреса, либо предоставив клиенту указать его в разделе "filename =" заголовок
Content-Disposition
. - Для каждого обработчика вызовите
handler.new_file
с соответствующими аргументами (издеваясь над именем поля) - Прочитайте тело запроса в кусках с помощью
request.read()
и вызываяhandler.receive_data_chunk()
для каждого фрагмента. - Для каждого вызова обработчика
handler.file_complete()
, и если он возвращает значение, это загруженный файл.
Как я могу вывести тип mime того, что отправляется? Если у меня все получится, Тело PUT - это просто файл без прелюдия. Поэтому я требую, чтобы пользователь задает тип mime в их заголовки?
Можно либо указать клиенту его в заголовке Content-Type, либо использовать модуль python mimetype, чтобы угадать тип носителя.
Мне было бы интересно узнать, как вы справляетесь с этим - это то, что я имел в виду, чтобы смотреть в себя, быть здоровым, если бы вы могли прокомментировать, чтобы сообщить мне, как это происходит!
Редактировать по Ninefingers по запросу, это то, что я сделал, и полностью основан на выше и источнике django.
upload_handlers = request.upload_handlers
content_type = str(request.META.get('CONTENT_TYPE', ""))
content_length = int(request.META.get('CONTENT_LENGTH', 0))
if content_type == "":
return HttpResponse(status=400)
if content_length == 0:
# both returned 0
return HttpResponse(status=400)
content_type = content_type.split(";")[0].strip()
try:
charset = content_type.split(";")[1].strip()
except IndexError:
charset = ""
# we can get the file name via the path, we don't actually
file_name = path.split("/")[-1:][0]
field_name = file_name
Поскольку я определяю API здесь, поддержка кросс-браузера не вызывает беспокойства. Что касается моего протокола, то не предоставление правильной информации является сломанным запросом. Я в двух умах о том, хочу ли я сказать image/jpeg; charset=binary
, или если я позволю использовать несуществующие кодировки. В любом случае, я устанавливаю установку Content-Type
действительным образом как ответственность на стороне клиента.
Аналогично, для моего протокола передается имя файла. Я не уверен, что для параметра field_name
, и источник не дал много подсказок.
То, что происходит ниже, на самом деле намного проще, чем кажется. Вы спросите каждого обработчика, будет ли он обрабатывать исходный ввод. Как автор вышеупомянутых состояний, у вас есть MemoryFileUploadHandler
и TemporaryFileUploadHandler
по умолчанию. Ну, оказывается, MemoryFileUploadHandler
будет при запросе создать new_file
решить, будет ли он обрабатывать файл или не обрабатывать его (на основе различных настроек). Если он решит, что это произойдет, он выдает исключение, иначе он не создаст файл и не перехватит другой обработчик.
Я не знаю, какова была цель counters
, но я сохранил ее из источника. Остальное должно быть простым.
counters = [0]*len(upload_handlers)
for handler in upload_handlers:
result = handler.handle_raw_input("",request.META,content_length,"","")
for handler in upload_handlers:
try:
handler.new_file(field_name, file_name,
content_type, content_length, charset)
except StopFutureHandlers:
break
for i, handler in enumerate(upload_handlers):
while True:
chunk = request.read(handler.chunk_size)
if chunk:
handler.receive_data_chunk(chunk, counters[i])
counters[i] += len(chunk)
else:
# no chunk
break
for i, handler in enumerate(upload_handlers):
file_obj = handler.file_complete(counters[i])
if not file_obj:
# some indication this didn't work?
return HttpResponse(status=500)
else:
# handle file obj!