Descriptive error from FileUploadParser when filename not included. (#4340)

* Descriptive error from FileUploadParser when filename not included.
* Consistent handling of upload filenames
This commit is contained in:
Tom Christie 2016-08-01 18:44:58 +01:00 committed by GitHub
parent 46a44e52aa
commit 3ef3fee926
2 changed files with 33 additions and 7 deletions

View File

@ -118,6 +118,10 @@ class FileUploadParser(BaseParser):
Parser for file upload data. Parser for file upload data.
""" """
media_type = '*/*' media_type = '*/*'
errors = {
'unhandled': 'FileUpload parse error - none of upload handlers can handle the stream',
'no_filename': 'Missing filename. Request should include a Content-Disposition header with a filename parameter.',
}
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
@ -134,6 +138,9 @@ class FileUploadParser(BaseParser):
upload_handlers = request.upload_handlers upload_handlers = request.upload_handlers
filename = self.get_filename(stream, media_type, parser_context) filename = self.get_filename(stream, media_type, parser_context)
if not filename:
raise ParseError(self.errors['no_filename'])
# Note that this code is extracted from Django's handling of # Note that this code is extracted from Django's handling of
# file uploads in MultiPartParser. # file uploads in MultiPartParser.
content_type = meta.get('HTTP_CONTENT_TYPE', content_type = meta.get('HTTP_CONTENT_TYPE',
@ -146,7 +153,7 @@ class FileUploadParser(BaseParser):
# See if the handler will want to take care of the parsing. # See if the handler will want to take care of the parsing.
for handler in upload_handlers: for handler in upload_handlers:
result = handler.handle_raw_input(None, result = handler.handle_raw_input(stream,
meta, meta,
content_length, content_length,
None, None,
@ -178,10 +185,10 @@ class FileUploadParser(BaseParser):
for index, handler in enumerate(upload_handlers): for index, handler in enumerate(upload_handlers):
file_obj = handler.file_complete(counters[index]) file_obj = handler.file_complete(counters[index])
if file_obj: if file_obj is not None:
return DataAndFiles({}, {'file': file_obj}) return DataAndFiles({}, {'file': file_obj})
raise ParseError("FileUpload parse error - "
"none of upload handlers can handle the stream") raise ParseError(self.errors['unhandled'])
def get_filename(self, stream, media_type, parser_context): def get_filename(self, stream, media_type, parser_context):
""" """

View File

@ -2,8 +2,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import pytest
from django import forms from django import forms
from django.core.files.uploadhandler import MemoryFileUploadHandler from django.core.files.uploadhandler import (
MemoryFileUploadHandler, TemporaryFileUploadHandler
)
from django.test import TestCase from django.test import TestCase
from django.utils.six.moves import StringIO from django.utils.six.moves import StringIO
@ -63,8 +66,9 @@ class TestFileUploadParser(TestCase):
parser = FileUploadParser() parser = FileUploadParser()
self.stream.seek(0) self.stream.seek(0)
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = '' self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
with self.assertRaises(ParseError): with pytest.raises(ParseError) as excinfo:
parser.parse(self.stream, None, self.parser_context) parser.parse(self.stream, None, self.parser_context)
assert str(excinfo.value) == 'Missing filename. Request should include a Content-Disposition header with a filename parameter.'
def test_parse_missing_filename_multiple_upload_handlers(self): def test_parse_missing_filename_multiple_upload_handlers(self):
""" """
@ -78,8 +82,23 @@ class TestFileUploadParser(TestCase):
MemoryFileUploadHandler() MemoryFileUploadHandler()
) )
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = '' self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
with self.assertRaises(ParseError): with pytest.raises(ParseError) as excinfo:
parser.parse(self.stream, None, self.parser_context) parser.parse(self.stream, None, self.parser_context)
assert str(excinfo.value) == 'Missing filename. Request should include a Content-Disposition header with a filename parameter.'
def test_parse_missing_filename_large_file(self):
"""
Parse raw file upload when filename is missing with TemporaryFileUploadHandler.
"""
parser = FileUploadParser()
self.stream.seek(0)
self.parser_context['request'].upload_handlers = (
TemporaryFileUploadHandler(),
)
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
with pytest.raises(ParseError) as excinfo:
parser.parse(self.stream, None, self.parser_context)
assert str(excinfo.value) == 'Missing filename. Request should include a Content-Disposition header with a filename parameter.'
def test_get_filename(self): def test_get_filename(self):
parser = FileUploadParser() parser = FileUploadParser()