base file upload handler classes and the builtin concrete subclasses any error having to do with uploading files this exception is raised when an upload must abort if connectionreset is true django knows will halt the upload without consuming the rest of the upload this will cause the browser to show a connection reset error this exception is raised by an upload handler that wants to skip a given file upload handlers that have handled a file and do not want future handlers to run should raise this exception instead of returning none base class for streaming upload handlers handle the raw input from the client parameters inputdata an object that supports reading via read meta request meta contentlength the integer value of the contentlength header from the client boundary the boundary from the contenttype header be sure to prepend two signal that a new file has been started warning as with any data from the client you should not trust contentlength and sometimes won t even get it receive data from the streamed upload parser start is the position in the file of the chunk signal that a file has completed file size corresponds to the actual size accumulated by all the chunks subclasses should return a valid uploadedfile object signal that the upload is complete subclasses should perform cleanup that is necessary for this handler signal that the upload was interrupted subclasses should perform cleanup that is necessary for this handler upload handler that streams data into a temporary file create the file object to append to as data is coming in file upload handler to stream uploads into memory used for small files use the contentlength to signal whether or not this handler should be used check the contentlength header to see if we should if the post is too large we cannot use the memory handler add the data to the bytesio file if self activated self file writerawdata else return rawdata def filecompleteself filesize given a path to a handler return an instance of that handler e g from django http import httprequest request httprequest loadhandler django core files uploadhandler temporaryfileuploadhandler request temporaryfileuploadhandler object at 0x any error having to do with uploading files this exception is raised when an upload must abort if connection_reset is true django knows will halt the upload without consuming the rest of the upload this will cause the browser to show a connection reset error this exception is raised by an upload handler that wants to skip a given file upload handlers that have handled a file and do not want future handlers to run should raise this exception instead of returning none base class for streaming upload handlers the default chunk size is 64 kb handle the raw input from the client parameters input_data an object that supports reading via read meta request meta content_length the integer value of the content length header from the client boundary the boundary from the content type header be sure to prepend two signal that a new file has been started warning as with any data from the client you should not trust content_length and sometimes won t even get it receive data from the streamed upload parser start is the position in the file of the chunk signal that a file has completed file size corresponds to the actual size accumulated by all the chunks subclasses should return a valid uploadedfile object signal that the upload is complete subclasses should perform cleanup that is necessary for this handler signal that the upload was interrupted subclasses should perform cleanup that is necessary for this handler upload handler that streams data into a temporary file create the file object to append to as data is coming in file upload handler to stream uploads into memory used for small files use the content_length to signal whether or not this handler should be used check the content length header to see if we should if the post is too large we cannot use the memory handler add the data to the bytesio file return a file object if this handler is activated given a path to a handler return an instance of that handler e g from django http import httprequest request httprequest load_handler django core files uploadhandler temporaryfileuploadhandler request temporaryfileuploadhandler object at 0x
import os
from io import BytesIO

from django.conf import settings
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
from django.utils.module_loading import import_string

__all__ = [
    "UploadFileException",
    "StopUpload",
    "SkipFile",
    "FileUploadHandler",
    "TemporaryFileUploadHandler",
    "MemoryFileUploadHandler",
    "load_handler",
    "StopFutureHandlers",
]


class UploadFileException(Exception):
    

    pass


class StopUpload(UploadFileException):
    

    def __init__(self, connection_reset=False):
        
        self.connection_reset = connection_reset

    def __str__(self):
        if self.connection_reset:
            return "StopUpload: Halt current upload."
        else:
            return "StopUpload: Consume request data, then halt."


class SkipFile(UploadFileException):
    

    pass


class StopFutureHandlers(UploadFileException):
    

    pass


class FileUploadHandler:
    

    chunk_size = 64 * 2**10  

    def __init__(self, request=None):
        self.file_name = None
        self.content_type = None
        self.content_length = None
        self.charset = None
        self.content_type_extra = None
        self.request = request

    def handle_raw_input(
        self, input_data, META, content_length, boundary, encoding=None
    ):
        
        pass

    def new_file(
        self,
        field_name,
        file_name,
        content_type,
        content_length,
        charset=None,
        content_type_extra=None,
    ):
        
        self.field_name = field_name
        self.file_name = file_name
        self.content_type = content_type
        self.content_length = content_length
        self.charset = charset
        self.content_type_extra = content_type_extra

    def receive_data_chunk(self, raw_data, start):
        
        raise NotImplementedError(
            "subclasses of FileUploadHandler must provide a receive_data_chunk() method"
        )

    def file_complete(self, file_size):
        
        raise NotImplementedError(
            "subclasses of FileUploadHandler must provide a file_complete() method"
        )

    def upload_complete(self):
        
        pass

    def upload_interrupted(self):
        
        pass


class TemporaryFileUploadHandler(FileUploadHandler):
    

    def new_file(self, *args, **kwargs):
        
        super().new_file(*args, **kwargs)
        self.file = TemporaryUploadedFile(
            self.file_name, self.content_type, 0, self.charset, self.content_type_extra
        )

    def receive_data_chunk(self, raw_data, start):
        self.file.write(raw_data)

    def file_complete(self, file_size):
        self.file.seek(0)
        self.file.size = file_size
        return self.file

    def upload_interrupted(self):
        if hasattr(self, "file"):
            temp_location = self.file.temporary_file_path()
            try:
                self.file.close()
                os.remove(temp_location)
            except FileNotFoundError:
                pass


class MemoryFileUploadHandler(FileUploadHandler):
    

    def handle_raw_input(
        self, input_data, META, content_length, boundary, encoding=None
    ):
        
        
        
        self.activated = content_length <= settings.FILE_UPLOAD_MAX_MEMORY_SIZE

    def new_file(self, *args, **kwargs):
        super().new_file(*args, **kwargs)
        if self.activated:
            self.file = BytesIO()
            raise StopFutureHandlers()

    def receive_data_chunk(self, raw_data, start):
        
        if self.activated:
            self.file.write(raw_data)
        else:
            return raw_data

    def file_complete(self, file_size):
        
        if not self.activated:
            return

        self.file.seek(0)
        return InMemoryUploadedFile(
            file=self.file,
            field_name=self.field_name,
            name=self.file_name,
            content_type=self.content_type,
            size=file_size,
            charset=self.charset,
            content_type_extra=self.content_type_extra,
        )


def load_handler(path, *args, **kwargs):
    
    return import_string(path)(*args, **kwargs)