diff options
| author | Michael Elovskikh | 2013-05-04 14:58:21 +0600 | 
|---|---|---|
| committer | Michael Elovskikh | 2013-05-04 14:58:21 +0600 | 
| commit | e36e4f48ad481b4303e68ed524677add07b224f7 (patch) | |
| tree | 6e97a37b8ae8628781750c002fd40935fbb71f9a /rest_framework/parsers.py | |
| parent | 318fdaabe560c99de4983e0a3cdcb79756baaf01 (diff) | |
| download | django-rest-framework-e36e4f48ad481b4303e68ed524677add07b224f7.tar.bz2 | |
Codebase improvements on FileUploadParser
* Added docstrings.
* Added `FileUploadParser.get_filename` to make it easier to override.
* Added url kwargs filename detection step.
* Updated tests corresponding to these changes.
Diffstat (limited to 'rest_framework/parsers.py')
| -rw-r--r-- | rest_framework/parsers.py | 45 | 
1 files changed, 32 insertions, 13 deletions
| diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py index 6ba05aef..7eb92184 100644 --- a/rest_framework/parsers.py +++ b/rest_framework/parsers.py @@ -215,16 +215,19 @@ class FileUploadParser(BaseParser):      media_type = '*/*'      def parse(self, stream, media_type=None, parser_context=None): +        """ +        Returns a DataAndFiles object. + +        `.data` will be None (we expect request body to be a file content). +        `.files` will be a `QueryDict` containing one 'file' elemnt - a parsed file. +        """ +          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 +        upload_handlers = request.upload_handlers +        filename = self.get_filename(stream, media_type, parser_context)          content_type = meta.get('HTTP_CONTENT_TYPE', meta.get('CONTENT_TYPE', ''))          try: @@ -233,28 +236,28 @@ class FileUploadParser(BaseParser):              content_length = None          # See if the handler will want to take care of the parsing. -        for handler in request.upload_handlers: +        for handler in 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]}) +                return DataAndFiles(None, {'file': result[1]}) -        possible_sizes = [x.chunk_size for x in request.upload_handlers if x.chunk_size] +        possible_sizes = [x.chunk_size for x in 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) +        counters = [0] * len(upload_handlers) -        for handler in request.upload_handlers: +        for handler in 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): +            for i, handler in enumerate(upload_handlers):                  chunk_length = len(chunk)                  chunk = handler.receive_data_chunk(chunk, counters[i])                  counters[i] += chunk_length @@ -262,7 +265,23 @@ class FileUploadParser(BaseParser):                      # If the chunk received by the handler is None, then don't continue.                      break -        for i, handler in enumerate(request.upload_handlers): +        for i, handler in enumerate(upload_handlers):              file_obj = handler.file_complete(counters[i])              if file_obj:                  return DataAndFiles(None, {'file': file_obj}) + +    def get_filename(self, stream, media_type, parser_context): +        """ +        Detects the uploaded file name. First searches a 'filename' url kwarg. +        Then tries to parse Content-Disposition header. +        """ +        try: +            return parser_context['kwargs']['filename'] +        except KeyError: +            pass +        try: +            meta = parser_context['request'].META +            disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION']) +            return disposition[1]['filename'] +        except (AttributeError, KeyError): +            pass | 
