Skip to content

Commit 3ef3fee

Browse files
authored
Descriptive error from FileUploadParser when filename not included. (#4340)
* Descriptive error from FileUploadParser when filename not included. * Consistent handling of upload filenames
1 parent 46a44e5 commit 3ef3fee

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

rest_framework/parsers.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ class FileUploadParser(BaseParser):
118118
Parser for file upload data.
119119
"""
120120
media_type = '*/*'
121+
errors = {
122+
'unhandled': 'FileUpload parse error - none of upload handlers can handle the stream',
123+
'no_filename': 'Missing filename. Request should include a Content-Disposition header with a filename parameter.',
124+
}
121125

122126
def parse(self, stream, media_type=None, parser_context=None):
123127
"""
@@ -134,6 +138,9 @@ def parse(self, stream, media_type=None, parser_context=None):
134138
upload_handlers = request.upload_handlers
135139
filename = self.get_filename(stream, media_type, parser_context)
136140

141+
if not filename:
142+
raise ParseError(self.errors['no_filename'])
143+
137144
# Note that this code is extracted from Django's handling of
138145
# file uploads in MultiPartParser.
139146
content_type = meta.get('HTTP_CONTENT_TYPE',
@@ -146,7 +153,7 @@ def parse(self, stream, media_type=None, parser_context=None):
146153

147154
# See if the handler will want to take care of the parsing.
148155
for handler in upload_handlers:
149-
result = handler.handle_raw_input(None,
156+
result = handler.handle_raw_input(stream,
150157
meta,
151158
content_length,
152159
None,
@@ -178,10 +185,10 @@ def parse(self, stream, media_type=None, parser_context=None):
178185

179186
for index, handler in enumerate(upload_handlers):
180187
file_obj = handler.file_complete(counters[index])
181-
if file_obj:
188+
if file_obj is not None:
182189
return DataAndFiles({}, {'file': file_obj})
183-
raise ParseError("FileUpload parse error - "
184-
"none of upload handlers can handle the stream")
190+
191+
raise ParseError(self.errors['unhandled'])
185192

186193
def get_filename(self, stream, media_type, parser_context):
187194
"""

tests/test_parsers.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
from __future__ import unicode_literals
44

5+
import pytest
56
from django import forms
6-
from django.core.files.uploadhandler import MemoryFileUploadHandler
7+
from django.core.files.uploadhandler import (
8+
MemoryFileUploadHandler, TemporaryFileUploadHandler
9+
)
710
from django.test import TestCase
811
from django.utils.six.moves import StringIO
912

@@ -63,8 +66,9 @@ def test_parse_missing_filename(self):
6366
parser = FileUploadParser()
6467
self.stream.seek(0)
6568
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
66-
with self.assertRaises(ParseError):
69+
with pytest.raises(ParseError) as excinfo:
6770
parser.parse(self.stream, None, self.parser_context)
71+
assert str(excinfo.value) == 'Missing filename. Request should include a Content-Disposition header with a filename parameter.'
6872

6973
def test_parse_missing_filename_multiple_upload_handlers(self):
7074
"""
@@ -78,8 +82,23 @@ def test_parse_missing_filename_multiple_upload_handlers(self):
7882
MemoryFileUploadHandler()
7983
)
8084
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
81-
with self.assertRaises(ParseError):
85+
with pytest.raises(ParseError) as excinfo:
8286
parser.parse(self.stream, None, self.parser_context)
87+
assert str(excinfo.value) == 'Missing filename. Request should include a Content-Disposition header with a filename parameter.'
88+
89+
def test_parse_missing_filename_large_file(self):
90+
"""
91+
Parse raw file upload when filename is missing with TemporaryFileUploadHandler.
92+
"""
93+
parser = FileUploadParser()
94+
self.stream.seek(0)
95+
self.parser_context['request'].upload_handlers = (
96+
TemporaryFileUploadHandler(),
97+
)
98+
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
99+
with pytest.raises(ParseError) as excinfo:
100+
parser.parse(self.stream, None, self.parser_context)
101+
assert str(excinfo.value) == 'Missing filename. Request should include a Content-Disposition header with a filename parameter.'
83102

84103
def test_get_filename(self):
85104
parser = FileUploadParser()

0 commit comments

Comments
 (0)