Hello! I need to use a 3rd party client that sends files using a chunked transfer encoding to a DRF route of my Django app. I tried to set up a custom parser, but the stream
is always None. It works without a problem when I send a file without chunked encoding. When looking at the source code of DRF it seems that chunked requests are not supported as the stream is set to None
when no Content-Length
is provided (which is the case in chunked encoding). Is there some workaround, or can I find an example somewhere of how to read a chunked data stream from a request?
copy-pasting this from an old project (3.2), I hope it helps!
MIDDLEWARE = [
# you might want to experiment with the order of the middleware,
# depending on what's going on in your app
...
'this_is_a_module.middlewares.ChunkedTransferMiddleware',
...
]
from django.utils.deprecation import MiddlewareMixin
class ChunkedTransferMiddleware(MiddlewareMixin):
def process_request(self, request):
if 'HTTP_TRANSFER_ENCODING' in request.META and request.META['HTTP_TRANSFER_ENCODING'] == 'chunked':
try:
# assemble chunks into the complete stream
request._body = b''
while True:
chunk_size = int(request.readline(), 16) # read the size of the chunk
if chunk_size == 0:
break # Last chunk
request._body += request.read(chunk_size) # read the chunk
request.read(2) # read the trailing '\r\n'
request._read_started = False
except Exception as e:
raise ValueError("Failed to read chunked request: {}".format(str(e)))
from rest_framework.parsers import BaseParser
class RawDataParser(BaseParser):
"""
Plain text parser.
"""
media_type = 'application/octet-stream'
def parse(self, stream, media_type=None, parser_context=None):
return stream.body
from rest_framework.views import APIView
from your_app.parsers import RawDataParser
class ThisIsAview(APIView):
parser_classes = (RawDataParser,)
def post(self, request, *args, **kwargs):
# bunch of things here
data = request.data
return Response({'status': 'received', 'data': data})
That looks pretty cool. I never thought about putting it in a middleware. I will try it out. Thanks a lot!