Skip to content

Instantly share code, notes, and snippets.

@gcatlin
Created June 25, 2012 17:09
Show Gist options
  • Save gcatlin/2989928 to your computer and use it in GitHub Desktop.
Save gcatlin/2989928 to your computer and use it in GitHub Desktop.
Django middleware for handling non-multipart uploads
class ApplicationOctetStreamHandlerMiddleware():
def process_request(self, request):
# @TODO support base64 encoding
# @TODO support content-disposition header and filename
content_type = request.META.get('CONTENT_TYPE')
try:
content_length = int(request.META.get('CONTENT_LENGTH', 0))
except (ValueError, TypeError):
content_length = 0
if not request.method in ('POST', 'PUT'):
return None
if not content_type == 'application/octet-stream':
return None
request._post = QueryDict('')
request._files = MultiValueDict()
# HTTP spec says that Content-Length >= 0 is valid
if content_length == 0:
return None
handlers = request.upload_handlers
unused_handlers = []
# For compatibility with low-level network APIs (with 32-bit integers),
# the chunk size should be < 2^31, but still divisible by 4.
possible_sizes = [x.chunk_size for x in handlers if x.chunk_size]
chunk_size = min([2**31-4] + possible_sizes)
# See if the handler will want to take care of the parsing.
# This allows overriding everything if somebody wants it.
for handler in handlers:
result = handler.handle_raw_input(request, request.META,
content_length, '', encoding=None)
if result is not None:
return result[0], result[1]
try:
for i, handler in enumerate(handlers):
handler.new_file('', '', content_type, content_length,
charset=None)
except StopFutureHandlers:
# put aside the remaining handlers
unused_handlers = handlers[i+1:]
handlers = handlers[:i+1]
counters = [0]*len(handlers)
while True:
chunk = request.read(chunk_size)
if not chunk:
break
for i, handler in enumerate(handlers):
handler.receive_data_chunk(chunk, counters[i])
counters[i] += len(chunk)
for i, handler in enumerate(handlers):
file_obj = handler.file_complete(counters[i])
if file_obj is not None:
request.FILES.appendlist('', file_obj)
for handler in handlers + unused_handlers:
handler.upload_complete()
return None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment