FileUploadParser. Raising StopFutureHandlers removes any handlers not yet run for the active set. Closes #2109.

This commit is contained in:
Tom Christie 2014-12-02 13:52:46 +00:00
parent e30e3f6dfc
commit 0359e9250d
2 changed files with 37 additions and 8 deletions

View File

@ -256,23 +256,24 @@ class FileUploadParser(BaseParser):
chunks = ChunkIter(stream, chunk_size) chunks = ChunkIter(stream, chunk_size)
counters = [0] * len(upload_handlers) counters = [0] * len(upload_handlers)
for handler in upload_handlers: for index, handler in enumerate(upload_handlers):
try: try:
handler.new_file(None, filename, content_type, handler.new_file(None, filename, content_type,
content_length, encoding) content_length, encoding)
except StopFutureHandlers: except StopFutureHandlers:
upload_handlers = upload_handlers[:index + 1]
break break
for chunk in chunks: for chunk in chunks:
for i, handler in enumerate(upload_handlers): for index, handler in enumerate(upload_handlers):
chunk_length = len(chunk) chunk_length = len(chunk)
chunk = handler.receive_data_chunk(chunk, counters[i]) chunk = handler.receive_data_chunk(chunk, counters[index])
counters[i] += chunk_length counters[index] += chunk_length
if chunk is None: if chunk is None:
break break
for i, handler in enumerate(upload_handlers): for index, handler in enumerate(upload_handlers):
file_obj = handler.file_complete(counters[i]) file_obj = handler.file_complete(counters[index])
if file_obj: if file_obj:
return DataAndFiles(None, {'file': file_obj}) return DataAndFiles(None, {'file': file_obj})
raise ParseError("FileUpload parse error - " raise ParseError("FileUpload parse error - "

View File

@ -1,12 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from rest_framework.compat import StringIO
from django import forms from django import forms
from django.core.files.uploadhandler import MemoryFileUploadHandler from django.core.files.uploadhandler import MemoryFileUploadHandler
from django.test import TestCase from django.test import TestCase
from django.utils import unittest from django.utils import unittest
from rest_framework.compat import etree from rest_framework.compat import etree
from rest_framework.compat import StringIO
from rest_framework.exceptions import ParseError
from rest_framework.parsers import FormParser, FileUploadParser from rest_framework.parsers import FormParser, FileUploadParser
from rest_framework.parsers import XMLParser from rest_framework.parsers import XMLParser
import datetime import datetime
@ -104,13 +105,40 @@ class TestFileUploadParser(TestCase):
self.parser_context = {'request': request, 'kwargs': {}} self.parser_context = {'request': request, 'kwargs': {}}
def test_parse(self): def test_parse(self):
""" Make sure the `QueryDict` works OK """ """
Parse raw file upload.
"""
parser = FileUploadParser() parser = FileUploadParser()
self.stream.seek(0) self.stream.seek(0)
data_and_files = parser.parse(self.stream, None, self.parser_context) data_and_files = parser.parse(self.stream, None, self.parser_context)
file_obj = data_and_files.files['file'] file_obj = data_and_files.files['file']
self.assertEqual(file_obj._size, 14) self.assertEqual(file_obj._size, 14)
def test_parse_missing_filename(self):
"""
Parse raw file upload when filename is missing.
"""
parser = FileUploadParser()
self.stream.seek(0)
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
with self.assertRaises(ParseError):
parser.parse(self.stream, None, self.parser_context)
def test_parse_missing_filename_multiple_upload_handlers(self):
"""
Parse raw file upload with multiple handlers when filename is missing.
Regression test for #2109.
"""
parser = FileUploadParser()
self.stream.seek(0)
self.parser_context['request'].upload_handlers = (
MemoryFileUploadHandler(),
MemoryFileUploadHandler()
)
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
with self.assertRaises(ParseError):
parser.parse(self.stream, None, self.parser_context)
def test_get_filename(self): def test_get_filename(self):
parser = FileUploadParser() parser = FileUploadParser()
filename = parser.get_filename(self.stream, None, self.parser_context) filename = parser.get_filename(self.stream, None, self.parser_context)