Django 1.3 是可以接受的。所以我可以
要么做点什么
request.raw_post_data 或
request.read() (或者一些
其他更好的访问方法)。任何
想法?
您不想接触request.raw_post_data - 这意味着将整个请求正文读入内存,如果您正在谈论文件上传可能会非常大,所以request.read() 是要走的路.您也可以使用 Django HttpRequest 中挖掘以找出使用私有接口的正确方法,然后确保您的代码也将与 Django 兼容是一个真正的拖累>= 1.3。
我建议你要做的是复制existing file upload behaviour parts of the MultiPartParser class:
- 从
request.upload_handlers 检索上传处理程序(默认为MemoryFileUploadHandler 和TemporaryFileUploadHandler)
- 确定请求的内容长度(在
HttpRequest 或 MultiPartParser 中搜索 Content-Length 以查看执行此操作的正确方法。)
- 确定上传文件的文件名,方法是让客户端使用 url 的最后一个路径部分指定它,或者让客户端在 the
Content-Disposition header 的“filename=”部分指定它。
- 对于每个处理程序,使用相关参数调用
handler.new_file(模拟字段名称)
- 使用
request.read()分块读取请求正文,并为每个块调用handler.receive_data_chunk()。
- 对于每个处理程序调用
handler.file_complete(),如果它返回一个值,那就是上传的文件。
我怎样才能推断出什么的 mime 类型
正在发送?如果我做对了,一个
PUT 正文只是没有的文件
序幕。因此,我是否要求
用户指定 MIME 类型
他们的标题?
要么让客户端在 Content-Type 标头中指定,要么使用python's mimetype module 猜测媒体类型。
我很想知道你是如何处理这件事的——这是我一直想要调查自己的事情,如果你能发表评论让我知道进展如何,那就太好了!
按要求由 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!