async def upload_fileobj(self, Fileobj: BinaryIO, Bucket: str, Key: str, ExtraArgs: Optional[Dict[str, Any]] = None,
                         Callback: Optional[Callable[[int], None]] = None,
                         Config: Optional[S3TransferConfig] = None):
    """Upload a file-like object to S3.

    The file-like object must be in binary mode.

    This is a managed transfer which will perform a multipart upload in
    multiple threads if necessary.

    Usage::

        import boto3
        s3 = boto3.client('s3')

        with open('filename', 'rb') as data:
            s3.upload_fileobj(data, 'mybucket', 'mykey')

    :type Fileobj: a file-like object
    :param Fileobj: A file-like object to upload. At a minimum, it must
        implement the `read` method, and must return bytes.

    :type Bucket: str
    :param Bucket: The name of the bucket to upload to.

    :type Key: str
    :param Key: The name of the key to upload to.

    :type ExtraArgs: dict
    :param ExtraArgs: Extra arguments that may be passed to the
        client operation.

    :type Callback: method
    :param Callback: A method which takes a number of bytes transferred to
        be periodically called during the upload.

    :type Config: boto3.s3.transfer.TransferConfig
    :param Config: The transfer configuration to be used when performing the
        upload.
    """
    if not ExtraArgs:
        ExtraArgs = {}

    # I was debating setting up a queue etc...
    # If its too slow I'll then be bothered
    multipart_chunksize = 8388608 if Config is None else Config.multipart_chunksize
    io_chunksize = 262144 if Config is None else Config.io_chunksize
    # max_concurrency = 10 if Config is None else Config.max_concurrency
    # max_io_queue = 100 if config is None else Config.max_io_queue

    # Start multipart upload

    resp = await self.create_multipart_upload(Bucket=Bucket, Key=Key, **ExtraArgs)
    upload_id = resp['UploadId']

    part = 0
    parts = []
    running = True
    sent_bytes = 0

    try:
        while running:
            part += 1
            multipart_payload = b''
            while len(multipart_payload) < multipart_chunksize:
                if asyncio.iscoroutinefunction(Fileobj.read):  # handles if we pass in aiofiles obj
                    data = await Fileobj.read(io_chunksize)
                else:
                    data = Fileobj.read(io_chunksize)

                if data == b'':  # End of file
                    running = False
                    break
                multipart_payload += data

            # Submit part to S3
            resp = await self.upload_part(
                Body=multipart_payload,
                Bucket=Bucket,
                Key=Key,
                PartNumber=part,
                UploadId=upload_id
            )
            parts.append({'ETag': resp['ETag'], 'PartNumber': part})
            sent_bytes += len(multipart_payload)
            try:
                Callback(sent_bytes)  # Attempt to call the callback, if it fails, ignore, if no callback, ignore
            except:  # noqa: E722
                pass

        # By now the uploads must have been done
        await self.complete_multipart_upload(
            Bucket=Bucket,
            Key=Key,
            UploadId=upload_id,
            MultipartUpload={'Parts': parts}
        )
    except:  # noqa: E722
        # Cancel multipart upload
        await self.abort_multipart_upload(
            Bucket=Bucket,
            Key=Key,
            UploadId=upload_id
        )

        raise
Upload a file-like object to S3.

    The file-like object must be in binary mode.

    This is a managed transfer which will perform a multipart upload in
    multiple threads if necessary.

    Usage::

        import boto3
        s3 = boto3.client('s3')

        with open('filename', 'rb') as data:
            s3.upload_fileobj(data, 'mybucket', 'mykey')

    :type Fileobj: a file-like object
    :param Fileobj: A file-like object to upload. At a minimum, it must
        implement the `read` method, and must return bytes.

    :type Bucket: str
    :param Bucket: The name of the bucket to upload to.

    :type Key: str
    :param Key: The name of the key to upload to.

    :type ExtraArgs: dict
    :param ExtraArgs: Extra arguments that may be passed to the
        client operation.

    :type Callback: method
    :param Callback: A method which takes a number of bytes transferred to
        be periodically called during the upload.

    :type Config: boto3.s3.transfer.TransferConfig
    :param Config: The transfer configuration to be used when performing the
        upload.