mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 03:23:59 +03:00
Merge pull request #1838 from jbittel/fix-encoded-filename-rfc6266
Support RFC6266 encoded filenames
This commit is contained in:
commit
5bbfef36f4
|
@ -11,7 +11,7 @@ from django.http import QueryDict
|
||||||
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
|
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
|
||||||
from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
|
from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from rest_framework.compat import etree, yaml, force_text
|
from rest_framework.compat import etree, yaml, force_text, urlparse
|
||||||
from rest_framework.exceptions import ParseError
|
from rest_framework.exceptions import ParseError
|
||||||
from rest_framework import renderers
|
from rest_framework import renderers
|
||||||
import json
|
import json
|
||||||
|
@ -290,6 +290,22 @@ class FileUploadParser(BaseParser):
|
||||||
try:
|
try:
|
||||||
meta = parser_context['request'].META
|
meta = parser_context['request'].META
|
||||||
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8'))
|
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8'))
|
||||||
return force_text(disposition[1]['filename'])
|
filename_parm = disposition[1]
|
||||||
|
if 'filename*' in filename_parm:
|
||||||
|
return self.get_encoded_filename(filename_parm)
|
||||||
|
return force_text(filename_parm['filename'])
|
||||||
except (AttributeError, KeyError):
|
except (AttributeError, KeyError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_encoded_filename(self, filename_parm):
|
||||||
|
"""
|
||||||
|
Handle encoded filenames per RFC6266. See also:
|
||||||
|
http://tools.ietf.org/html/rfc2231#section-4
|
||||||
|
"""
|
||||||
|
encoded_filename = force_text(filename_parm['filename*'])
|
||||||
|
try:
|
||||||
|
charset, lang, filename = encoded_filename.split('\'', 2)
|
||||||
|
filename = urlparse.unquote(filename)
|
||||||
|
except (ValueError, LookupError):
|
||||||
|
filename = force_text(filename_parm['filename'])
|
||||||
|
return filename
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from rest_framework.compat import StringIO
|
from rest_framework.compat import StringIO
|
||||||
from django import forms
|
from django import forms
|
||||||
|
@ -113,3 +115,25 @@ class TestFileUploadParser(TestCase):
|
||||||
parser = FileUploadParser()
|
parser = FileUploadParser()
|
||||||
filename = parser.get_filename(self.stream, None, self.parser_context)
|
filename = parser.get_filename(self.stream, None, self.parser_context)
|
||||||
self.assertEqual(filename, 'file.txt')
|
self.assertEqual(filename, 'file.txt')
|
||||||
|
|
||||||
|
def test_get_encoded_filename(self):
|
||||||
|
parser = FileUploadParser()
|
||||||
|
|
||||||
|
self.__replace_content_disposition('inline; filename*=utf-8\'\'ÀĥƦ.txt')
|
||||||
|
filename = parser.get_filename(self.stream, None, self.parser_context)
|
||||||
|
self.assertEqual(filename, 'ÀĥƦ.txt')
|
||||||
|
|
||||||
|
self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8\'\'ÀĥƦ.txt')
|
||||||
|
filename = parser.get_filename(self.stream, None, self.parser_context)
|
||||||
|
self.assertEqual(filename, 'ÀĥƦ.txt')
|
||||||
|
|
||||||
|
self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8\'en-us\'ÀĥƦ.txt')
|
||||||
|
filename = parser.get_filename(self.stream, None, self.parser_context)
|
||||||
|
self.assertEqual(filename, 'ÀĥƦ.txt')
|
||||||
|
|
||||||
|
self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8--ÀĥƦ.txt')
|
||||||
|
filename = parser.get_filename(self.stream, None, self.parser_context)
|
||||||
|
self.assertEqual(filename, 'fallback.txt')
|
||||||
|
|
||||||
|
def __replace_content_disposition(self, disposition):
|
||||||
|
self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = disposition
|
||||||
|
|
Loading…
Reference in New Issue
Block a user