def METHOD_NAME(
    self, src: Union[str, os.PathLike], dst: str, paths: Optional[storage.Paths] = None
) -> None:
    src = os.fspath(src)
    prefix = self.get_storage_prefix(dst)
    logging.info(f"Uploading to s3: prefix={prefix}")
    upload_paths = paths if paths is not None else self._list_directory(src)
    for rel_path in sorted(upload_paths):
        key_name = f"{prefix}/{rel_path}"
        logging.debug(f"Uploading {rel_path} to s3://{self.bucket_name}/{key_name}")
        if rel_path.endswith("/"):
            # Create empty S3 keys for each subdirectory to mimic what the S3 console does to
            # represent empty directories.
            if not self._use_minio_workaround:
                self.bucket.put_object(Key=key_name, Body=b"")
            else:
                # boto3 will puke on the following MinIO response if you ever create a
                # directory by uploading an empty blob.  Uploading a normal file in the
                # directory and then deleting it seems to cause MinIO to prune the empty
                # directory.  The AWS authentication scheme is complex and not worth the
                # effort for supporting empty directories, so... just ignore empty directories.
                pass
        else:
            abs_path = os.path.join(src, rel_path)
            self.bucket.upload_file(abs_path, key_name)