aboutsummaryrefslogtreecommitdiff
"""Utilities to deal with uploaded files."""
import hashlib
from pathlib import Path
from datetime import datetime

from flask import current_app

from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage

from .chunks import chunked_binary_read

def save_file(fileobj: FileStorage, upload_dir: Path, hashed: bool = True) -> Path:
    """Save the uploaded file and return the path."""
    assert bool(fileobj), "Invalid file object!"
    hashed_name = (
        hashlib.sha512(
            f"{fileobj.filename}::{datetime.now().isoformat()}".encode("utf8")
        ).hexdigest()
        if hashed else
        fileobj.filename)
    filename = Path(secure_filename(hashed_name)) # type: ignore[arg-type]
    if not upload_dir.exists():
        upload_dir.mkdir()

    filepath = Path(upload_dir, filename)
    fileobj.save(filepath)
    return filepath


def fullpath(filename: str):
    """Get a file's full path. This makes use of `flask.current_app`."""
    return Path(current_app.config["UPLOAD_FOLDER"], filename).absolute()


def sha256_digest_over_file(filepath: Path) -> str:
    """Compute the sha256 digest over a file's contents."""
    filehash = hashlib.sha256()
    for chunk in chunked_binary_read(filepath):
        filehash.update(chunk)

    return filehash.hexdigest()