示例#1
0
文件: tasks.py 项目: quru/qis
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)
示例#2
0
def delete_folder(db_folder, user_account, data_manager, permissions_manager, logger):
    """
    Recursively deletes a disk folder, it's sub-folders and images, adds image
    deletion history, and marks as deleted all the associated database records.
    This method may therefore take a long time.

    The user account must have Delete Folder permission for the containing
    folder, or alternatively have the file admin system permission.
    The root folder cannot be deleted.

    This method creates and commits its own separate database connection
    in an attempt to keep the operation is as atomic as possible. Note however
    that if there is an error deleting the folder tree (in the database or on
    disk), operations already performed are not rolled back, and the database
    may become out of sync with the file system.

    Returns the updated folder object, including all affected sub-folders.

    Raises a ValueError if the source folder is the root folder.
    Raises an OSError on error deleting disk files or folders.
    Raises a DBError for database errors.
    Raises a SecurityError if the current user does not have sufficient
    permission to perform the delete.
    """
    db_session = data_manager.db_get_session()
    success = False
    try:
        # Connect db_folder to our database session
        db_folder = data_manager.get_folder(db_folder.id, _db_session=db_session)
        if not db_folder:
            raise DoesNotExistError('Folder ID %d does not exist' % db_folder.id)

        # Don't allow deletion of root folder
        if db_folder.is_root():
            raise ValueError('Cannot delete the root folder')

        # Require Delete Folder permission on the parent folder
        if user_account:
            permissions_manager.ensure_folder_permitted(
                db_folder.parent,
                FolderPermission.ACCESS_DELETE_FOLDER,
                user_account
            )

        logger.info(
            'Disk folder %s is being deleted by %s' %
            (db_folder.path, user_account.username if user_account else 'System')
        )

        # Delete the disk folder first, as this is the most likely thing to fail.
        # Note that this might involve deleting files and directories we haven't
        # got database entries for (but that doesn't matter).
        filesystem_manager.delete_dir(db_folder.path, recursive=True)

        # Now delete all the data
        data_manager.delete_folder(
            db_folder,
            purge=False,
            history_user=user_account,
            history_info='Folder deleted by user',
            _db_session=db_session,
            _commit=False
        )

        # OK!
        logger.info(
            'Disk folder %s successfully deleted by %s' %
            (db_folder.path, user_account.username if user_account else 'System')
        )
        success = True
        return db_folder

    finally:
        # Commit or rollback database
        try:
            if success:
                db_session.commit()
            else:
                db_session.rollback()
        finally:
            db_session.close()