Added FileUploadParser refs #7

This commit is contained in:
Michael Elovskikh 2013-05-03 01:37:25 +06:00
parent 198b679e02
commit 0c85768435

View File

@ -6,9 +6,10 @@ on the request, such as form content or json encoded data.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.core.files.uploadhandler import StopFutureHandlers
from django.http import QueryDict from django.http import QueryDict
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
from rest_framework.compat import yaml, etree from rest_framework.compat import yaml, etree
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from rest_framework.compat import six from rest_framework.compat import six
@ -205,3 +206,63 @@ class XMLParser(BaseParser):
pass pass
return value return value
class FileUploadParser(BaseParser):
"""
Parser for file upload data.
"""
media_type = '*/*'
def parse(self, stream, media_type=None, parser_context=None):
parser_context = parser_context or {}
request = parser_context['request']
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
meta = request.META
try:
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'])
filename = disposition[1]['filename']
except KeyError:
filename = None
content_type = meta.get('HTTP_CONTENT_TYPE', meta.get('CONTENT_TYPE', ''))
try:
content_length = int(meta.get('HTTP_CONTENT_LENGTH', meta.get('CONTENT_LENGTH', 0)))
except (ValueError, TypeError):
content_length = None
# See if the handler will want to take care of the parsing.
for handler in request.upload_handlers:
result = handler.handle_raw_input(None,
meta,
content_length,
None,
encoding)
if result is not None:
return DataAndFiles(result[0], {'file': result[1]})
possible_sizes = [x.chunk_size for x in request.upload_handlers if x.chunk_size]
chunk_size = min([2**31-4] + possible_sizes)
chunks = ChunkIter(stream, chunk_size)
counters = [0] * len(request.upload_handlers)
for handler in request.upload_handlers:
try:
handler.new_file(None, filename, content_type, content_length, encoding)
except StopFutureHandlers:
break
for chunk in chunks:
for i, handler in enumerate(request.upload_handlers):
chunk_length = len(chunk)
chunk = handler.receive_data_chunk(chunk, counters[i])
counters[i] += chunk_length
if chunk is None:
# If the chunk received by the handler is None, then don't continue.
break
for i, handler in enumerate(request.upload_handlers):
file_obj = handler.file_complete(counters[i])
if file_obj:
return DataAndFiles(None, {'file': file_obj})