Exemple #1
0
def burst_pdf(**kwargs):
    """
    A task that creates a sub-folder next to a PDF file and extracts all
    pages from the PDF as PNG files into the sub-folder.
    """
    from flask_app import app
    from filesystem_manager import get_abs_path, get_burst_path, get_file_data
    from filesystem_manager import delete_dir, make_dirs, path_exists
    from filesystem_sync import delete_folder
    from imagemagick import imagemagick_burst_pdf
    from models import Folder
    from util import get_file_extension

    (src,) = _extract_parameters(["src"], **kwargs)
    burst_folder_rel = get_burst_path(src)

    # Ensure src is a PDF
    if get_file_extension(src) not in app.config["PDF_FILE_TYPES"]:
        app.log.warn("Cannot burst non-PDF file: " + src)
        return

    # See if the burst folder already exists (in the database and on disk)
    db_folder = app.data_engine.get_folder(folder_path=burst_folder_rel)
    if db_folder is not None and db_folder.status == Folder.STATUS_ACTIVE:
        # Wipe the folder, old images, data, and uncache the old images
        delete_folder(db_folder, None, app.data_engine, None, app.log)
        deleted_ids = app.data_engine.list_image_ids(db_folder)
        for image_id in deleted_ids:
            app.image_engine._uncache_image_id(image_id)

    # See if the burst folder already exists (just on disk)
    if path_exists(burst_folder_rel, require_directory=True):
        # Wipe the folder and old images
        delete_dir(burst_folder_rel, recursive=True)

    # Create the burst folder and burst
    pdf_data = get_file_data(src)
    if pdf_data is not None:
        make_dirs(burst_folder_rel)
        burst_folder_abs = get_abs_path(burst_folder_rel)
        if not imagemagick_burst_pdf(pdf_data, burst_folder_abs, app.config["PDF_BURST_DPI"]):
            app.log.warn("Failed to burst PDF: " + src)
    else:
        app.log.warn("Cannot burst PDF, file not found: " + src)
Exemple #2
0
def auto_sync_existing_file(rel_path, data_manager, task_manager,
                            anon_history=True, burst_pdf='auto', _db_session=None):
    """
    Returns the database record for an image file that is known to exist,
    creating a new record or un-deleting an old record if required,
    and always returning a value.

    This method creates anonymous image history entries when anon_history is
    True. If the current user should be recorded against an action, the caller
    should set anon_history to False and manually add a history record.

    The bursting of PDF files is also initiated here. By default, a PDF file
    will be burst if no burst folder already exists. Setting burst_pdf to False
    disables this, or setting burst_pdf to True will force it to be burst again.

    Raises a DoesNotExistError if the image path is in fact invalid.
    Raises a SecurityError if the image path is outside of IMAGES_BASE_DIR.
    Raises a DBError if the database record cannot be created.
    """
    db_own = (_db_session is None)
    db_session = _db_session or data_manager.db_get_session()
    db_error = False
    try:
        # Get (or create) db record for the file
        on_create = on_image_db_create_anon_history if anon_history \
            else on_image_db_create
        db_image = data_manager.get_or_create_image(
            rel_path, on_create, _db_session=db_session
        )
        if not db_image:
            # Not expected
            raise DBError('Failed to add image to database: ' + rel_path)

        # Burst PDF if we need to
        # TODO This would be better in on_image_db_create if we can get a task_manager without
        #      importing the one from flask_app. Needs to be compatible with the task server.
        if burst_pdf and app.config['PDF_BURST_TO_PNG']:
            can_burst = get_file_extension(rel_path) in app.config['PDF_FILE_TYPES']
            if can_burst:
                if burst_pdf == 'auto':
                    burst_pdf = not path_exists(
                        get_burst_path(rel_path),
                        require_directory=True
                    )
                if burst_pdf:
                    burst_pdf_file(rel_path, task_manager)

        if db_image.status == Image.STATUS_ACTIVE:
            # The normal case
            return db_image
        else:
            # We need to undelete the database record
            db_image.status = Image.STATUS_ACTIVE
            if anon_history:
                on_image_db_create_anon_history(db_image)
            else:
                on_image_db_create(db_image)

            # Check whether the file's folder needs to be undeleted too
            if db_image.folder.status == Folder.STATUS_DELETED:
                auto_sync_existing_folder(
                    db_image.folder.path,
                    data_manager,
                    _db_session=db_session
                )
            return db_image
    except:
        db_error = True
        raise
    finally:
        if db_own:
            try:
                if db_error:
                    db_session.rollback()
                else:
                    db_session.commit()
            finally:
                db_session.close()