Обработка предупреждений презентаций в Java

Обзор

Aspose.Slides может сообщать о восстанавливаемых проблемах во время загрузки, рендеринга, конвертации или сохранения презентации. Примеры включают повреждённые исходные записи, контент, который невозможно сохранить, замену шрифтов и ограничения целевого формата. Обратный вызов предупреждения позволяет приложению фиксировать эти условия и решать, может ли текущая операция продолжиться.

Реализуйте интерфейс IWarningCallback и проверяйте значения, возвращаемые через IWarningInfo, используя методы getWarningType и getDescription. Верните ReturnAction.Continue, чтобы принять предупреждение, или ReturnAction.Abort, чтобы прервать операцию.

Используйте LoadOptions.setWarningCallback для предупреждений, возникающих при открытии презентации. Классы параметров рендеринга и экспорта наследуют SaveOptions.setWarningCallback, который получает предупреждения от рендеринга слайдов, конвертации и сохранения. Поскольку само предупреждение не указывает операцию приложения, связывайте каждый экземпляр обратного вызова с этапом операции при построении объединённого отчёта.

Предупреждения и исключения

Предупреждение описывает условие, из которого Aspose.Slides может восстановиться, если обратный вызов вернёт ReturnAction.Continue. Исключение означает, что запрошенная операция не может завершиться нормально; исключения не преобразуются в предупреждения и не могут быть обработаны политикой предупреждений.

Возврат ReturnAction.Abort просит диспетчер предупреждений завершить текущую операцию, вызвав исключение. Публичное исключение зависит от операции и формата презентации. Например, при загрузке может возникнуть PptxReadException или PptReadException, тогда как при сохранении или экспорте может возникнуть PptxException. Обрабатывайте исключение на границе операции и используйте отчёт о предупреждениях для определения, была ли остановка вызвана политикой приложения, а не только типом исключения или его сообщением. Обратный вызов фиксирует предупреждение перед возвратом ReturnAction.Abort, обеспечивая доступность причины для приложения.

Категории предупреждений

Класс WarningType предоставляет целочисленные константы для следующих категорий:

Тип предупреждения Значение Типичная политика
SourceFileCorruption Исходная презентация содержит повреждения, которые могут сделать документ, сохранённый в оригинальном формате, непригодным. Прервать.
DataLoss Текст, диаграммы, изображения или другие данные могут отсутствовать после загрузки или сохранения. Прервать.
MajorFormattingLoss Презентация может потерять важное форматирование. Прервать в режиме строгой валидации; иначе фиксировать и продолжать.
MinorFormattingLoss Может возникнуть ограниченное различие в форматировании. Фиксировать для диагностики и продолжать.
CompatibilityIssue Результат может не открываться или работать некорректно в некоторых приложениях или старых версиях. Записывать в лог и продолжать, если совместимость не обязательна.
UnexpectedContent Исходный файл содержит неподдерживаемый или нераспознанный контент, влияние которого пока неизвестно. Фиксировать и продолжать, либо рассматривать как ошибку в строгой политике.

Категория должна определять решение политики. Сохраняйте значение, возвращаемое getDescription, для диагностики, но не полагайтесь на его формулировку в логике приложения, так как текст сообщения может различаться между сценариями предупреждений и версиями продукта.

Сбор и классификация предупреждений

Следующий пример использует один отчёт уровня приложения для полного конвейера обработки. Отдельный экземпляр обратного вызова помечает предупреждения из фаз загрузки, рендеринга, конвертации в PDF и сохранения PPTX. Политика прерывает работу при обнаружении повреждения источника или потери данных, при желании прерывает при серьёзной потере форматирования и продолжает при остальных предупреждениях.

import com.aspose.slides.IImage;
import com.aspose.slides.IWarningCallback;
import com.aspose.slides.IWarningInfo;
import com.aspose.slides.ImageFormat;
import com.aspose.slides.LoadOptions;
import com.aspose.slides.PdfOptions;
import com.aspose.slides.PptxOptions;
import com.aspose.slides.Presentation;
import com.aspose.slides.RenderingOptions;
import com.aspose.slides.ReturnAction;
import com.aspose.slides.SaveFormat;
import com.aspose.slides.WarningType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class PresentationWarningExample {
    public static void main(String[] args) {
        WarningReport report = new WarningReport();
        WarningPolicy policy = new WarningPolicy(true);
        boolean completed = processPresentation("input.pptx", report, policy);

        System.out.println(completed ? "Processing completed." : "Processing stopped.");

        for (WarningEntry entry : report.getEntries()) {
            String typeName = warningTypeName(entry.type);
            System.out.println("[" + entry.stage + "] " + typeName + ": " + entry.description);
        }
    }

    private static boolean processPresentation(String inputPath, WarningReport report, WarningPolicy policy) {
        try {
            LoadOptions loadOptions = new LoadOptions();
            ReportingWarningCallback callback = new ReportingWarningCallback(OperationStage.Loading, report, policy);
            loadOptions.setWarningCallback(callback);

            Presentation presentation = new Presentation(inputPath, loadOptions);
            try {
                if (!renderFirstSlide(presentation, report, policy)) {
                    return false;
                }

                if (!convertToPdf(presentation, report, policy)) {
                    return false;
                }

                return saveValidatedCopy(presentation, report, policy);
            }
            finally {
                presentation.dispose();
            }
        }
        catch (Exception exception) {
            System.err.println("Loading stopped: " + exception.getMessage());
            return false;
        }
    }

    private static boolean renderFirstSlide(Presentation presentation, WarningReport report, WarningPolicy policy) {
        if (presentation.getSlides().size() == 0) {
            System.err.println("Rendering stopped: the presentation has no slides.");
            return false;
        }

        try {
            RenderingOptions options = new RenderingOptions();
            ReportingWarningCallback callback = new ReportingWarningCallback(OperationStage.Rendering, report, policy);
            options.setWarningCallback(callback);

            IImage image = presentation.getSlides().get_Item(0).getImage(options);
            try {
                image.save("slide-1.png", ImageFormat.Png);
                return true;
            }
            finally {
                image.dispose();
            }
        }
        catch (Exception exception) {
            System.err.println("Rendering stopped: " + exception.getMessage());
            return false;
        }
    }

    private static boolean convertToPdf(Presentation presentation, WarningReport report, WarningPolicy policy) {
        try {
            PdfOptions options = new PdfOptions();
            ReportingWarningCallback callback = new ReportingWarningCallback(OperationStage.Conversion, report, policy);
            options.setWarningCallback(callback);

            presentation.save("converted.pdf", SaveFormat.Pdf, options);
            return true;
        }
        catch (Exception exception) {
            System.err.println("Conversion stopped: " + exception.getMessage());
            return false;
        }
    }

    private static boolean saveValidatedCopy(Presentation presentation, WarningReport report, WarningPolicy policy) {
        try {
            PptxOptions options = new PptxOptions();
            ReportingWarningCallback callback = new ReportingWarningCallback(OperationStage.Saving, report, policy);
            options.setWarningCallback(callback);

            presentation.save("validated-output.pptx", SaveFormat.Pptx, options);
            return true;
        }
        catch (Exception exception) {
            System.err.println("Saving stopped: " + exception.getMessage());
            return false;
        }
    }

    private static String warningTypeName(int warningType) {
        switch (warningType) {
            case WarningType.SourceFileCorruption:
                return "SourceFileCorruption";
            case WarningType.DataLoss:
                return "DataLoss";
            case WarningType.MajorFormattingLoss:
                return "MajorFormattingLoss";
            case WarningType.MinorFormattingLoss:
                return "MinorFormattingLoss";
            case WarningType.CompatibilityIssue:
                return "CompatibilityIssue";
            case WarningType.UnexpectedContent:
                return "UnexpectedContent";
            default:
                return "Unknown (" + warningType + ")";
        }
    }

    private enum OperationStage {
        Loading,
        Rendering,
        Conversion,
        Saving
    }

    private static final class WarningEntry {
        final OperationStage stage;
        final int type;
        final String description;

        WarningEntry(OperationStage stage, int type, String description) {
            this.stage = stage;
            this.type = type;
            this.description = description;
        }
    }

    private static final class WarningReport {
        private final List<WarningEntry> entries = new ArrayList<WarningEntry>();

        List<WarningEntry> getEntries() {
            return Collections.unmodifiableList(entries);
        }

        void add(OperationStage stage, IWarningInfo warning) {
            WarningEntry entry = new WarningEntry(stage, warning.getWarningType(), warning.getDescription());
            entries.add(entry);
        }
    }

    private static final class WarningPolicy {
        private final boolean abortOnMajorFormattingLoss;

        WarningPolicy(boolean abortOnMajorFormattingLoss) {
            this.abortOnMajorFormattingLoss = abortOnMajorFormattingLoss;
        }

        int getAction(int warningType) {
            if (warningType == WarningType.SourceFileCorruption || warningType == WarningType.DataLoss) {
                return ReturnAction.Abort;
            }

            if (warningType == WarningType.MajorFormattingLoss && abortOnMajorFormattingLoss) {
                return ReturnAction.Abort;
            }

            return ReturnAction.Continue;
        }
    }

    private static final class ReportingWarningCallback implements IWarningCallback {
        private final OperationStage stage;
        private final WarningReport report;
        private final WarningPolicy policy;

        ReportingWarningCallback(OperationStage stage, WarningReport report, WarningPolicy policy) {
            this.stage = stage;
            this.report = report;
            this.policy = policy;
        }

        @Override
        public int warning(IWarningInfo warning) {
            report.add(stage, warning);
            return policy.getAction(warning.getWarningType());
        }
    }
}

Передайте false для параметра abortOnMajorFormattingLoss при создании WarningPolicy, если серьёзные различия в форматировании приемлемы. Проблемы совместимости, небольшая потеря форматирования и неожиданный контент всё равно сохраняются в отчёте, даже если операция продолжается. Расширьте WarningPolicy.getAction, если приложение должно отклонять любые из этих категорий.

Распространённые сценарии предупреждений

Предупреждения могут возникать на разных этапах рабочего процесса:

  • Цифровые подписи: Подписанная презентация может вызвать предупреждение при загрузке о том, что её подпись будет потеряна в процессе. Aspose.Slides сообщает об этом условии DataLoss через IPresentationSignedWarningInfo. Обратный вызов на этапе загрузки позволяет приложению отклонить файл или явно принять сообщённую потерю.
  • Замена шрифтов: Недоступный шрифт может быть заменён во время рендеринга слайда или экспорта. Предупреждения о замене шрифтов сообщаются как DataLoss, поэтому строгая политика выше прерывает работу, даже если приложение сочтет конкретную замену визуально приемлемой. Чтобы увидеть это поведение, используйте входную презентацию с текстом, написанным шрифтом, недоступным в среде выполнения. Описание предупреждения указывает замену; настройте требуемые шрифты или правила замены шрифтов перед повторной попыткой.
  • Неподдерживаемый или неожиданный контент: Загрузчик может встретить записи презентации или функции, которые он не распознаёт. Такие предупреждения могут использовать UnexpectedContent или более тяжёлую категорию, когда известны потери данных или форматирования.
  • Совместимость формата: Сохранение в другой формат презентации может опустить функции или дать результат, который ведёт себя иначе в некоторых приложениях. Например, сохранение презентации с более чем восемью горизонтальными или восемью вертикальными направляющими черчения в устаревший PPT приводит к CompatibilityIssue. Обратный вызов на этапе сохранения может зафиксировать потерю и продолжить, либо отклонить её, если требуется сохранение всех направляющих.
  • Поведение загрузки: Параметры загрузки и устаревшее поведение также могут генерировать предупреждения. Например, IObsoletePresLockingBehaviorWarningInfo определяет использование устаревшего поведения блокировки презентации как CompatibilityIssue.

Предупреждения зависят от исходного документа, целевого формата, операции и версии Aspose.Slides. Не следует предполагать, что каждый файл генерирует предупреждение или что сценарий всегда относится к единственной категории.

Безопасная обработка прерванных операций

Когда обратный вызов возвращает ReturnAction.Abort, не используйте объект, который не удалось загрузить, и не полагайтесь на то, что вывод рендеринга или сохранения завершён. Операция может завершиться после создания выходного файла, но до его окончательной записи.

Сохраняйте проверенные результаты в отдельный путь, например validated-output.pptx. Заменяйте существующую презентацию только после успешного завершения операции, когда отчёт о предупреждениях удовлетворяет политике приложения, и файл может быть открыт и проверен. Это предотвращает перезапись валидного исходного файла частичным или отклонённым результатом.

Пустой отчёт о предупреждениях не гарантирует, что все исходные функции сохранены. Выполняйте любые дополнительные проверки содержимого и визуального отображения, требуемые приложением. См. также Open Presentations и Save Presentations.

FAQ

Можно ли обработать все ошибки Aspose.Slides с помощью обратного вызова предупреждения?

Нет. Он обрабатывает лишь восстанавливаемые условия, сообщаемые как предупреждения. Исключения, возникающие независимо от обратного вызова, необходимо обрабатывать в приложении вокруг вызова загрузки, рендеринга, конвертации или сохранения.

Гарантирует ли возврат ReturnAction.Continue идентичный вывод?

Нет. Он лишь разрешает продолжить обработку. Сообщённое условие всё равно может вызвать различия в данных, форматировании или совместимости, поэтому следует просмотреть собранные типы и описания предупреждений.

Как приложению определить операцию, породившую предупреждение?

Создайте отдельный экземпляр обратного вызова для каждой операции и сохраняйте определённый приложением этап вместе со значениями, возвращаемыми getWarningType и getDescription, как показано в примере.