Skip to content

Commit 0359e92

Browse files
committed
FileUploadParser. Raising StopFutureHandlers removes any handlers not yet run for the active set. Closes #2109.
1 parent e30e3f6 commit 0359e92

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

rest_framework/parsers.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,23 +256,24 @@ def parse(self, stream, media_type=None, parser_context=None):
256256
chunks = ChunkIter(stream, chunk_size)
257257
counters = [0] * len(upload_handlers)
258258

259-
for handler in upload_handlers:
259+
for index, handler in enumerate(upload_handlers):
260260
try:
261261
handler.new_file(None, filename, content_type,
262262
content_length, encoding)
263263
except StopFutureHandlers:
264+
upload_handlers = upload_handlers[:index + 1]
264265
break
265266

266267
for chunk in chunks:
267-
for i, handler in enumerate(upload_handlers):
268+
for index, handler in enumerate(upload_handlers):
268269
chunk_length = len(chunk)
269-
chunk = handler.receive_data_chunk(chunk, counters[i])
270-
counters[i] += chunk_length
270+
chunk = handler.receive_data_chunk(chunk, counters[index])
271+
counters[index] += chunk_length
271272
if chunk is None:
272273
break
273274

274-
for i, handler in enumerate(upload_handlers):
275-
file_obj = handler.file_complete(counters[i])
275+
for index, handler in enumerate(upload_handlers):
276+
file_obj = handler.file_complete(counters[index])
276277
if file_obj:
277278
return DataAndFiles(None, {'file': file_obj})
278279
raise ParseError("FileUpload parse error - "

tests/test_parsers.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# -*- coding: utf-8 -*-
22

33
from __future__ import unicode_literals
4-
from rest_framework.compat import StringIO
54
from django import forms
65
from django.core.files.uploadhandler import MemoryFileUploadHandler
76
from django.test import TestCase
87
from django.utils import unittest
98
from rest_framework.compat import etree
9+
from rest_framework.compat import StringIO
10+
from rest_framework.exceptions import ParseError
1011
from rest_framework.parsers import FormParser, FileUploadParser
1112
from rest_framework.parsers import XMLParser
1213
import datetime
@@ -104,13 +105,40 @@ class MockRequest(object):
104105
self.parser_context = {'request': request, 'kwargs': {}}
105106

106107
def test_parse(self):
107-
""" Make sure the `QueryDict` works OK """
108+
"""
109+
Parse raw file upload.
110+
"""
108111
parser = FileUploadParser()
109112
self.stream.seek(0)
110113
data_and_files = parser.parse(self.stream, None, self.parser_context)
111114
file_obj = data_and_files.files['file']
112115
self.assertEqual(file_obj._size, 14)
113116

117+
def test_parse_missing_filename(self):
118+
"""
119+
Parse raw file upload when filename is missing.
120+
"""
121+
parser = FileUploadParser()
122+
self.stream.seek(0)
123+
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
124+
with self.assertRaises(ParseError):
125+
parser.parse(self.stream, None, self.parser_context)
126+
127+
def test_parse_missing_filename_multiple_upload_handlers(self):
128+
"""
129+
Parse raw file upload with multiple handlers when filename is missing.
130+
Regression test for #2109.
131+
"""
132+
parser = FileUploadParser()
133+
self.stream.seek(0)
134+
self.parser_context['request'].upload_handlers = (
135+
MemoryFileUploadHandler(),
136+
MemoryFileUploadHandler()
137+
)
138+
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = ''
139+
with self.assertRaises(ParseError):
140+
parser.parse(self.stream, None, self.parser_context)
141+
114142
def test_get_filename(self):
115143
parser = FileUploadParser()
116144
filename = parser.get_filename(self.stream, None, self.parser_context)

0 commit comments

Comments
 (0)