mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-13 05:06:53 +03:00
Allow None filename on uploaded files
This commit is contained in:
parent
246a376dcf
commit
429e078eee
|
@ -114,6 +114,7 @@ If the view used with `FileUploadParser` is called with a `filename` URL keyword
|
||||||
|
|
||||||
* The `FileUploadParser` is for usage with native clients that can upload the file as a raw data request. For web-based uploads, or for native clients with multipart upload support, you should use the `MultiPartParser` parser instead.
|
* The `FileUploadParser` is for usage with native clients that can upload the file as a raw data request. For web-based uploads, or for native clients with multipart upload support, you should use the `MultiPartParser` parser instead.
|
||||||
* Since this parser's `media_type` matches any content type, `FileUploadParser` should generally be the only parser set on an API view.
|
* Since this parser's `media_type` matches any content type, `FileUploadParser` should generally be the only parser set on an API view.
|
||||||
|
* `FileUploadParser` respects Django's standard `FILE_UPLOAD_HANDLERS` setting, and the `request.upload_handlers` attribute. See the [Django documentation][upload-handlers] for more details.
|
||||||
|
|
||||||
##### Basic usage example:
|
##### Basic usage example:
|
||||||
|
|
||||||
|
@ -183,6 +184,7 @@ The following third party packages are also available.
|
||||||
|
|
||||||
[jquery-ajax]: http://api.jquery.com/jQuery.ajax/
|
[jquery-ajax]: http://api.jquery.com/jQuery.ajax/
|
||||||
[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
|
[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
|
||||||
|
[upload-handlers]: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#upload-handlers
|
||||||
[messagepack]: https://github.com/juanriaza/django-rest-framework-msgpack
|
[messagepack]: https://github.com/juanriaza/django-rest-framework-msgpack
|
||||||
[juanriaza]: https://github.com/juanriaza
|
[juanriaza]: https://github.com/juanriaza
|
||||||
[djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack
|
[djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack
|
||||||
|
|
|
@ -219,7 +219,7 @@ class FileUploadParser(BaseParser):
|
||||||
Returns a DataAndFiles object.
|
Returns a DataAndFiles object.
|
||||||
|
|
||||||
`.data` will be None (we expect request body to be a file content).
|
`.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.
|
`.files` will be a `QueryDict` containing one 'file' element.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
parser_context = parser_context or {}
|
parser_context = parser_context or {}
|
||||||
|
@ -229,9 +229,13 @@ 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)
|
||||||
|
|
||||||
content_type = meta.get('HTTP_CONTENT_TYPE', meta.get('CONTENT_TYPE', ''))
|
# Note that this code is extracted from Django's handling of
|
||||||
|
# file uploads in MultiPartParser.
|
||||||
|
content_type = meta.get('HTTP_CONTENT_TYPE',
|
||||||
|
meta.get('CONTENT_TYPE', ''))
|
||||||
try:
|
try:
|
||||||
content_length = int(meta.get('HTTP_CONTENT_LENGTH', meta.get('CONTENT_LENGTH', 0)))
|
content_length = int(meta.get('HTTP_CONTENT_LENGTH',
|
||||||
|
meta.get('CONTENT_LENGTH', 0)))
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
content_length = None
|
content_length = None
|
||||||
|
|
||||||
|
@ -245,6 +249,7 @@ class FileUploadParser(BaseParser):
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return DataAndFiles(None, {'file': result[1]})
|
return DataAndFiles(None, {'file': result[1]})
|
||||||
|
|
||||||
|
# This is the standard case.
|
||||||
possible_sizes = [x.chunk_size for x in 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)
|
chunk_size = min([2 ** 31 - 4] + possible_sizes)
|
||||||
chunks = ChunkIter(stream, chunk_size)
|
chunks = ChunkIter(stream, chunk_size)
|
||||||
|
@ -252,7 +257,8 @@ class FileUploadParser(BaseParser):
|
||||||
|
|
||||||
for handler in upload_handlers:
|
for handler in upload_handlers:
|
||||||
try:
|
try:
|
||||||
handler.new_file(None, filename, content_type, content_length, encoding)
|
handler.new_file(None, filename, content_type,
|
||||||
|
content_length, encoding)
|
||||||
except StopFutureHandlers:
|
except StopFutureHandlers:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -262,14 +268,14 @@ class FileUploadParser(BaseParser):
|
||||||
chunk = handler.receive_data_chunk(chunk, counters[i])
|
chunk = handler.receive_data_chunk(chunk, counters[i])
|
||||||
counters[i] += chunk_length
|
counters[i] += chunk_length
|
||||||
if chunk is None:
|
if chunk is None:
|
||||||
# If the chunk received by the handler is None, then don't continue.
|
|
||||||
break
|
break
|
||||||
|
|
||||||
for i, handler in enumerate(upload_handlers):
|
for i, handler in enumerate(upload_handlers):
|
||||||
file_obj = handler.file_complete(counters[i])
|
file_obj = handler.file_complete(counters[i])
|
||||||
if file_obj:
|
if file_obj:
|
||||||
return DataAndFiles(None, {'file': file_obj})
|
return DataAndFiles(None, {'file': file_obj})
|
||||||
raise ParseError("FileUpload parse error - none of upload handlers can handle the stream")
|
raise ParseError("FileUpload parse error - "
|
||||||
|
"none of upload handlers can handle the stream")
|
||||||
|
|
||||||
def get_filename(self, stream, media_type, parser_context):
|
def get_filename(self, stream, media_type, parser_context):
|
||||||
"""
|
"""
|
||||||
|
@ -286,4 +292,4 @@ class FileUploadParser(BaseParser):
|
||||||
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'])
|
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'])
|
||||||
return disposition[1]['filename']
|
return disposition[1]['filename']
|
||||||
except (AttributeError, KeyError):
|
except (AttributeError, KeyError):
|
||||||
raise ParseError("Filename must be set in Content-Disposition header.")
|
pass
|
||||||
|
|
Loading…
Reference in New Issue
Block a user