Джанго 1.3 приемлемо. Так что я могу
либо сделать что-то с
request.raw_post_data или
request.read () (или альтернативно некоторые
другой лучший способ доступа). любой
идеи?
Вы не хотите касаться request.raw_post_data
- это подразумевает чтение всего тела запроса в память, что, если вы говорите о загрузке файлов, может быть очень большой суммой, поэтому request.read()
- это путь , Вы можете сделать это и с Django <= 1.2, но это означает, что нужно покопаться в <code>HttpRequest, чтобы выяснить, как правильно использовать частные интерфейсы, и это реальная проблема, чтобы убедиться, что ваш код также будет совместим с Django. > = 1,3.
Я бы посоветовал вам скопировать существующие части поведения при загрузке файлов MultiPartParser
класса :
- Получите обработчики загрузки из
request.upload_handlers
(который по умолчанию будет MemoryFileUploadHandler
& TemporaryFileUploadHandler
)
- Определите длину содержимого запроса (Поиск Content-Length в
HttpRequest
или MultiPartParser
, чтобы увидеть правильный способ сделать это.)
- Определите имя файла загруженного файла, либо позволив клиенту указать это, используя последнюю часть пути URL, либо позволив клиенту указать его в части «filename =» заголовка
Content-Disposition
.
- Для каждого обработчика вызывать
handler.new_file
с соответствующими аргументами (макетировать имя поля)
- Считайте тело запроса в чанках, используя
request.read()
и вызывая handler.receive_data_chunk()
для каждого чанка.
- Для каждого вызова обработчика
handler.file_complete()
, и если он возвращает значение, это загруженный файл.
Как я могу вывести тип пантомимы, что
отправляется? Если я правильно понял,
PUT body - это просто файл без
прелюдия. Поэтому я требую, чтобы
пользователь указывает тип MIME в
их заголовки?
Либо разрешите клиенту указать его в заголовке Content-Type, либо используйте модуль mimetype python , чтобы угадать тип носителя.
Мне было бы интересно узнать, как вы справляетесь с этим - я хотел подумать о себе, было бы здорово, если бы вы могли прокомментировать, чтобы я знал, как это происходит!
Редактирование 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!