Учебник по GroupDocs Viewer для Java: Конвертация Word в HTML и отображение документов с комментариями

Введение

Если вам нужно конвертировать Word в HTML с сохранением каждой заметки, комментария или аннотации рецензента, вы попали в нужное место. Многие Java‑разработчики сталкиваются с проблемой, когда при конвертации документа теряется ценная обратная связь, встроенная в исходный файл. В этом учебнике мы покажем, как использовать GroupDocs Viewer для Java, чтобы конвертировать Word в HTML и отображать широкий спектр типов документов — Word, Excel, PowerPoint, PDF и другие — без потери данных комментариев.

Вы узнаете, почему GroupDocs Viewer — готовое к продакшну решение, как настроить окружение, какой код нужен, а также проверенные приёмы для поддержания высокой производительности даже с большими файлами.

Отображение документов с комментариями с помощью GroupDocs.Viewer для Java

Отображение документов с комментариями с помощью GroupDocs.Viewer для Java

Что вы освоите в этом учебнике:

  • Полная настройка и конфигурация GroupDocs Viewer
  • Пошаговая конвертация Word в HTML с сохранением комментариев
  • Общие решения проблем и подводные камни, которых следует избегать
  • Реальные шаблоны реализации и лучшие практики
  • Техники оптимизации производительности для продакшн‑использования

Быстрые ответы

  • Может ли GroupDocs Viewer конвертировать Word в HTML? Да — включите рендеринг HTML и поддержку комментариев одной строкой кода.
  • Остаются ли комментарии в выводе HTML? Абсолютно — setRenderComments(true) сохраняет каждый комментарий и аннотацию.
  • Какая версия Java требуется? JDK 8 или выше.
  • Нужна ли лицензия для продакшна? Полная лицензия удаляет водяные знаки и открывает все функции.
  • Как улучшить скорость рендеринга? Рендерите отдельные страницы, используйте внешние ресурсы и увеличьте размер кучи JVM.

Что такое «конвертация word в html» с комментариями?

«Конвертация Word в HTML» означает преобразование файла Microsoft Word .docx в готовый к веб‑использованию HTML‑документ с сохранением оригинального макета, стилей и всех встроенных комментариев. Этот процесс позволяет браузерам отображать документ точно так, как задумали авторы, включая обратную связь рецензентов.

Почему выбирать GroupDocs Viewer для Java?

Прежде чем погрузиться в код, давайте рассмотрим, почему GroupDocs Viewer является основной библиотекой для рендеринга документов на Java:

  • Более 170 поддерживаемых форматов — библиотека обрабатывает всё от DOCX до файлов CAD, предоставляя единственную зависимость для всех ваших потребностей в конвертации.
  • Не требуется установка сторонних офисных приложений — работает на любой ОС без необходимости в Microsoft Office, LibreOffice или других тяжёлых средах выполнения.
  • Сохраняет форматирование и аннотации — комментарии, сноски и отслеживание изменений сохраняются после конвертации.
  • Быстрый, лёгкий движок — типичный документ из 100 страниц рендерится менее чем за 2 секунды на стандартном 4‑ядерном сервере.
  • Подробная документация и активное сообщество — вы найдёте примеры, форумы и быструю поддержку, когда столкнётесь с проблемой.

Когда использовать этот подход

  • Создание веб‑просмотрщиков документов, которым необходимо отображать заметки рецензентов
  • Создание платформ совместного рецензирования, где обратная связь должна оставаться видимой
  • Конвертация устаревших контрактов для онлайн‑отображения в юридических порталах
  • Разработка e‑learning решений, встраивающих комментарии инструктора в учебные материалы

Необходимые условия и настройка окружения

Что понадобится

  • Java Development Kit (JDK) 8+ — среда выполнения, которая питает ваше приложение.
  • Maven 3.6+ — для управления зависимостями и сборки проекта.
  • IDE по вашему выбору — IntelliJ IDEA, Eclipse или VS Code.
  • Примерные документы с комментариями — файлы DOCX, XLSX, PPTX, содержащие заметки рецензентов.

Настройка среды разработки

Шаг 1: Проверка установки Java

Open a terminal and run:

java -version

Вы должны увидеть строку версии, начинающуюся с 1.8 или выше. Если нет, скачайте последнюю JDK с официального сайта Oracle или OpenJDK.

Шаг 2: Проверка установки Maven

Run:

mvn -v

Maven должен вывести свою версию и версию Java, которую использует. Установите Maven с сайта Apache, если команда не распознаётся.

Шаг 3: Создание нового Maven проекта

Generate a skeleton project with:

mvn archetype:generate -DgroupId=com.example.viewer -DartifactId=viewer-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Перейдите в только что созданную папку viewer-demo, и вы будете готовы добавить GroupDocs Viewer.

Настройка GroupDocs.Viewer для Java

Добавление зависимости

Первый шаг в любом учебнике по GroupDocs Viewer для Java — добавить библиотеку в ваш проект. Добавьте эту конфигурацию в файл pom.xml:

<dependency>
    <groupId>com.groupdocs</groupId>
    <artifactId>groupdocs-viewer</artifactId>
    <version>25.2</version>
</dependency>

Полезный совет: Всегда проверяйте страницу релизов GroupDocs для получения последней версии. Библиотека активно поддерживается, регулярно обновляется и исправляются ошибки.

Понимание вариантов лицензирования

GroupDocs предлагает гибкое лицензирование, которое подходит для разных потребностей проекта:

  • Бесплатная пробная версия (идеально для обучения): 30‑дневная оценка с полным доступом к функциям и водяными знаками оценки.
  • Временная лицензия (для разработки): Расширенная оценка без водяных знаков; идеально для проектов proof‑of‑concept. Запросите на странице временной лицензии GroupDocs.
  • Полная лицензия (готова к продакшну): Без ограничений и водяных знаков, разрешено коммерческое использование. Доступна на странице покупки GroupDocs.

Базовый шаблон инициализации

Вот основной шаблон, который вы будете использовать в течение всего учебника:

try (Viewer viewer = new Viewer("input.docx")) {
    // Rendering options will be set later
}

Почему этот шаблон работает:

  • Автоматическое управление ресурсами предотвращает утечки памяти.
  • Обработка исключений ловит распространённые проблемы доступа к файлам.
  • Чистый, читаемый код, который легко поддерживать в больших проектах.

Основная реализация: рендеринг документов с комментариями

Понимание процесса

When you render a document with GroupDocs Viewer, the library performs four key steps:

  1. Анализ документа — парсит входной файл и строит внутреннее представление.
  2. Извлечение комментариев — определяет каждый комментарий, сноску и аннотацию.
  3. Генерация HTML — создает чистый, соответствующий стандартам HTML, отражающий оригинальный макет.
  4. Обработка ресурсов — объединяет изображения, CSS и шрифты либо встроенно, либо как внешние файлы.

Пошаговая реализация

Шаг 1: Настройка путей к файлам

Организуйте пути ввода и вывода заранее, чтобы избежать ошибок, связанных с путями:

Path inputPath = Paths.get("documents/sample-with-comments.docx");
Path outputDir = Paths.get("output/html");
Files.createDirectories(outputDir);

Почему такой подход:

  • Использует современный Java NIO.2 Path API, который надёжнее, чем java.io.File.
  • Описательные имена переменных упрощают отладку.
  • Заполнитель {0} в шаблоне вывода автоматически заменяется номерами страниц.

Шаг 2: Настройка параметров рендеринга HTML

Здесь происходит магия. Мы сообщаем GroupDocs, как именно мы хотим, чтобы документ был отрендерен:

HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(outputDir);
viewOptions.setRenderComments(true);   // Preserve every comment
viewOptions.setPageNumberPrefix("page_");

HtmlViewOptions настраивает, как документ будет отрендерен в HTML, включая обработку ресурсов и рендеринг комментариев.

Ключевые детали конфигурации:

  • forEmbeddedResources() встраивает CSS, изображения и шрифты непосредственно в HTML, делая вывод портативным.
  • setRenderComments(true) — единственная строка, которая гарантирует, что конвертация word в html сохраняет все заметки рецензентов.
  • Альтернатива forExternalResources() позволяет хранить ресурсы отдельно, если вы предпочитаете более лёгкий HTML‑файл.

Шаг 3: Выполнение рендеринга

Теперь мы объединяем всё вместе:

try (Viewer viewer = new Viewer(inputPath.toFile())) {
    viewer.view(viewOptions);
}

Viewer — основной класс, используемый для загрузки документа и выполнения операций рендеринга.

Вызов view читает файл Word, извлекает комментарии, генерирует HTML‑страницы и записывает их в output/html. Каждая страница сохраняется как page_1.html, page_2.html и т.д.

Полный рабочий пример

Собрав все части вместе, вы получаете один исполняемый класс, который конвертирует документ Word в HTML, сохраняя комментарии. (Полный исходный код доступен в официальном репозитории GitHub.)

Расширенная конфигурация и параметры

Настройка динамических каталогов вывода

Для более крупных приложений вы можете генерировать каталоги вывода на основе идентификаторов пользователей или меток времени:

String userId = "12345";
Path dynamicOutput = Paths.get("output", userId, LocalDate.now().toString());
Files.createDirectories(dynamicOutput);
HtmlViewOptions dynamicOptions = HtmlViewOptions.forEmbeddedResources(dynamicOutput);

Распространённые проблемы и их устранение

Проблема 1: Ошибки «Файл не найден»

Убедитесь, что путь ввода абсолютный или относительный к рабочему каталогу, и проверьте права доступа к файлу. Использование объектов Path помогает избежать распространённых ошибок конкатенации строк.

Проблема 2: Комментарии не отображаются в выводе

Убедитесь, что setRenderComments(true) вызывается до viewer.view(). Также проверьте, что исходный документ действительно содержит комментарии; их можно просмотреть через viewer.getDocumentInfo().getComments().

Проблема 3: Ошибки «Недостаточно памяти» при работе с большими документами

GroupDocs Viewer потоково обрабатывает данные, но чрезвычайно большие файлы (> 500 страниц) всё равно могут перегрузить кучу JVM. Увеличьте размер кучи с помощью -Xmx4g или рендерите только необходимые страницы.

Проблема 4: Низкая производительность рендеринга

Рендерите конкретные диапазоны страниц, используя viewer.view(pageRange, viewOptions). Внешние ресурсы (forExternalResources()) также уменьшают размер HTML‑полезной нагрузки, ускоряя рендеринг в браузере.

Шаблоны реальной реализации

Шаблон 1: Интеграция в веб‑приложение

Интегрируйте логику рендеринга в контроллер Spring Boot для предоставления HTML по запросу:

@RestController
@RequestMapping("/api/view")
public class DocumentController {

    @GetMapping("/{id}")
    public ResponseEntity<Resource> renderDocument(@PathVariable String id) throws IOException {
        Path docPath = Paths.get("documents", id + ".docx");
        Path outDir = Files.createTempDirectory("viewer");
        HtmlViewOptions options = HtmlViewOptions.forEmbeddedResources(outDir);
        options.setRenderComments(true);
        try (Viewer viewer = new Viewer(docPath.toFile())) {
            viewer.view(options);
        }
        // Return the first HTML page as a Resource
        Path firstPage = outDir.resolve("page_1.html");
        Resource resource = new UrlResource(firstPage.toUri());
        return ResponseEntity.ok()
                .contentType(MediaType.TEXT_HTML)
                .body(resource);
    }
}

Шаблон 2: Пакетная обработка нескольких документов

Когда необходимо конвертировать всю папку файлов Word, пройдитесь по каталогу в цикле и переиспользуйте тот же экземпляр HtmlViewOptions, чтобы минимизировать накладные расходы на создание объектов.

Оптимизация производительности и лучшие практики

Советы по управлению памятью

  • Всегда используйте try‑with‑resources для экземпляров Viewer.
  • Обрабатывайте большие документы пакетами, а не загружайте всё в память сразу.
  • Отслеживайте использование кучи JVM с помощью инструментов, таких как VisualVM, и при необходимости корректируйте -Xmx.
  • Реализуйте правильное кэширование часто запрашиваемых документов, чтобы избежать повторного рендеринга.

Руководство по использованию ресурсов

Для небольших приложений (< 100 документов/день):

HtmlViewOptions options = HtmlViewOptions.forEmbeddedResources(Paths.get("output"));
options.setRenderComments(true);

Для приложений с высоким объёмом (1000+ документов/день):

HtmlViewOptions options = HtmlViewOptions.forExternalResources(Paths.get("output"));
options.setRenderComments(true);
options.setCacheEnabled(true);

Стратегии кэширования

Сохраняйте отрендеренный HTML в распределённом кэше (например, Redis), используя хеш документа в качестве ключа. При поступлении запроса сначала проверяйте кэш; если найдено, сразу отдавайте кэшированный HTML, обходя движок рендеринга.

Когда использовать GroupDocs Viewer vs альтернативы

GroupDocs Viewer идеально подходит для

  • Системы управления документами — необходимо отображать множество типов файлов с аннотациями.
  • Платформы совместного рецензирования — комментарии должны оставаться видимыми для всех участников.
  • Образовательные инструменты — заметки инструкторов отображаются рядом со слайдами лекций.
  • Юридические приложения — контракты с комментариями юристов требуют точного отображения.

Рассмотрите альтернативы, когда

  • Простое отображение PDF — встроенные в браузер PDF‑просмотрщики могут быть достаточными.
  • Базовое преобразование изображенийImageIO или аналогичные библиотеки легче.
  • Чистое извлечение текста — Apache POI или iText могут быть более подходящими.

Часто задаваемые вопросы

В: Могу ли я рендерить документы без комментариев?
О: Да — просто опустите вызов setRenderComments(true) или установите его в false.

В: Какие форматы файлов поддерживают рендеринг комментариев?
О: Большинство основных форматов — включая DOC/DOCX, XLS/XLSX, PPT/PPTX, PDF и многие другие. См. официальную документацию для полного списка.

В: Могу ли я настроить стилизацию HTML‑вывода?
О: Конечно. Используйте HtmlViewOptions.setEmbedResources(false), чтобы генерировать внешние CSS‑файлы, затем добавьте свою таблицу стилей после рендеринга.

В: Как обрабатывать документы, защищённые паролем?
О: Предоставьте экземпляр LoadOptions с паролем:

LoadOptions позволяет задавать параметры загрузки документа, такие как пароли.

LoadOptions loadOptions = new LoadOptions("myPassword");
try (Viewer viewer = new Viewer(inputPath.toFile(), loadOptions)) {
    viewer.view(viewOptions);
}

В: Можно ли рендерить только определённые страницы?
О: Да — используйте перегруженный метод view, который принимает коллекцию PageNumber:

PageNumber представляет конкретный индекс страницы, используемый при рендеринге подмножества страниц.

viewer.view(new int[]{1, 3, 5}, viewOptions);

В: Почему рендеринг медленный для больших документов?
О: Большие файлы требуют больше времени обработки. Ускорьте процесс, рендеря только необходимые страницы, используя внешние ресурсы, увеличивая кучу JVM и включив асинхронную обработку.

В: Как можно отслеживать прогресс рендеринга?
О: Хотя у GroupDocs Viewer нет встроенных обратных вызовов, вы можете измерять время операции с помощью System.nanoTime() до и после viewer.view(), чтобы записать длительность.

В: Что происходит, если исходный документ повреждён?
О: Библиотека бросает ViewerException. Оберните вызов в блок try‑catch и запишите ошибку для плавного деградирования.

В: Могу ли я использовать GroupDocs Viewer в коммерческом приложении?
О: Да, но требуется коммерческая лицензия. Бесплатная пробная версия включает водяные знаки, которые необходимо удалить для продакшн‑использования.

В: Есть ли ограничения по использованию?
О: Сама библиотека ограничений не накладывает, однако ваш лицензионный договор может определять лимиты использования. Проверьте ваш контракт для деталей.

В: Могу ли я распространять приложения, включающие GroupDocs Viewer?
О: Вы можете распространять своё приложение, но не можете распространять бинарные файлы библиотеки GroupDocs. Проверьте условия лицензии для соблюдения.

Следующие шаги и продвинутые темы

Теперь у вас есть прочная база для конвертации word в html с сохранением комментариев. Вот несколько направлений для углубления экспертизы:

  • Водяные знаки — добавляйте пользовательские водяные знаки на отрендеренные страницы для брендинга или конфиденциальности.
  • Извлечение метаданных — получайте автора, дату создания и количество страниц через viewer.getDocumentInfo().
  • Пользовательские просмотрщики — создавайте специализированные просмотрщики для PDF, таблиц или презентаций, которые скрывают или выделяют комментарии по‑разному.
  • Интеграция с облачным хранилищем — рендерьте файлы напрямую из AWS S3, Azure Blob или Google Drive без локального скачивания.

Рекомендуемый путь обучения

  • Экспериментируйте с различными типами файлов — попробуйте Excel, PowerPoint и PDF, чтобы увидеть, как обрабатываются комментарии в разных форматах.
  • Создайте простой веб‑просмотрщик — создайте минимальную HTML‑страницу, которая загружает сгенерированный HTML через <iframe> или AJAX.
  • Изучите экосистему GroupDocs — посмотрите GroupDocs Annotation, Comparison и Signature для сквозных документооборотных процессов.
  • Присоединяйтесь к сообществу — участвуйте в форуме GroupDocs для советов, примеров проектов и поддержки.

Получение помощи и поддержки

Официальные ресурсы

Ресурсы сообщества

  • Stack Overflow (tag: groupdocs-viewer)
  • Сообщества программирования на Reddit
  • Discord‑серверы для Java‑разработчиков

Последнее обновление: 2026-05-21
Тестировано с: GroupDocs.Viewer 25.2 for Java
Автор: GroupDocs

java -version
javac -version
mvn -version
mvn archetype:generate -DgroupId=com.example.documentviewer -DartifactId=groupdocs-viewer-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
<repositories>
   <repository>
      <id>repository.groupdocs.com</id>
      <name>GroupDocs Repository</name>
      <url>https://releases.groupdocs.com/viewer/java/</url>
   </repository>
</repositories>
<dependencies>
   <dependency>
      <groupId>com.groupdocs</groupId>
      <artifactId>groupdocs-viewer</artifactId>
      <version>25.2</version>
   </dependency>
</dependencies>
import com.groupdocs.viewer.Viewer;

// The try-with-resources pattern ensures proper cleanup
try (Viewer viewer = new Viewer("path/to/your/document.docx")) {
    // All rendering operations happen here
    // Resources are automatically closed when done
} catch (Exception e) {
    System.err.println("Error rendering document: " + e.getMessage());
    e.printStackTrace();
}
import java.nio.file.Path;
import java.nio.file.Paths;

// Create a descriptive output directory
Path outputDirectory = Paths.get("rendered-documents");
Path pageFilePathFormat = outputDirectory.resolve("page_{0}.html");
import com.groupdocs.viewer.options.HtmlViewOptions;

// Create HTML options with embedded resources
HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);

// The crucial setting – enable comment rendering!
viewOptions.setRenderComments(true);
import com.groupdocs.viewer.Viewer;

try (Viewer viewer = new Viewer("path/to/your/document.docx")) {
    // Create output directory if it doesn't exist
    if (!outputDirectory.toFile().exists()) {
        outputDirectory.toFile().mkdirs();
    }
    
    // Perform the actual rendering
    viewer.view(viewOptions);
    
    System.out.println("Document rendered successfully!");
    System.out.println("Output location: " + outputDirectory.toAbsolutePath());
    
} catch (Exception e) {
    System.err.println("Rendering failed: " + e.getMessage());
    e.printStackTrace();
}
package com.example.documentviewer;

import com.groupdocs.viewer.Viewer;
import com.groupdocs.viewer.options.HtmlViewOptions;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DocumentRenderer {
    
    public static void main(String[] args) {
        renderDocumentWithComments("sample-document.docx", "output");
    }
    
    public static void renderDocumentWithComments(String inputFile, String outputDir) {
        // Set up paths
        Path outputDirectory = Paths.get(outputDir);
        Path pageFilePathFormat = outputDirectory.resolve("page_{0}.html");
        
        // Configure rendering options
        HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);
        viewOptions.setRenderComments(true);
        
        // Render the document
        try (Viewer viewer = new Viewer(inputFile)) {
            // Ensure output directory exists
            outputDirectory.toFile().mkdirs();
            
            // Execute rendering
            viewer.view(viewOptions);
            
            System.out.println("✓ Document rendered with comments preserved");
            System.out.println("📂 Output directory: " + outputDirectory.toAbsolutePath());
            
        } catch (Exception e) {
            System.err.println("❌ Rendering failed: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
import java.nio.file.Path;
import java.nio.file.Paths;

public class PathManager {
    
    /**
     * Creates a structured output path based on document name and timestamp
     */
    public static Path getOutputDirectoryPath(String documentName) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String cleanDocName = documentName.replaceAll("[^a-zA-Z0-9]", "_");
        
        return Paths.get("rendered-docs")
                   .resolve(cleanDocName)
                   .resolve(timestamp);
    }
    
    /**
     * Simple output directory for basic use cases
     */
    public static Path getSimpleOutputPath(String folderName) {
        return Paths.get("output").resolve(folderName);
    }
}
// Always check if file exists before processing
Path inputPath = Paths.get("your-document.docx");
if (!inputPath.toFile().exists()) {
    throw new IllegalArgumentException("Input file not found: " + inputPath.toAbsolutePath());
}

// Check if file is readable
if (!inputPath.toFile().canRead()) {
    throw new IllegalArgumentException("Cannot read input file: " + inputPath.toAbsolutePath());
}
HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);
// This line is crucial – don't forget it!
viewOptions.setRenderComments(true);

// For debugging, you can verify the setting:
System.out.println("Comments enabled: " + viewOptions.isRenderComments());
// Increase JVM heap size when running
// java -Xmx2g -Xms1g YourApplication

// Or process documents page by page for very large files
HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);
viewOptions.setRenderComments(true);

// Render only specific pages if needed
viewer.view(viewOptions, 1, 2, 3); // Renders only pages 1, 2, and 3
// Use external resources for faster processing of multiple pages
HtmlViewOptions viewOptions = HtmlViewOptions.forExternalResources(
    pageFilePathFormat, 
    "resources/page_{0}/", 
    "resources/page_{0}/{0}"
);

// Enable caching if processing the same document multiple times
// (Note: Implement caching at application level)
@RestController
@RequestMapping("/api/documents")
public class DocumentController {
    
    @PostMapping("/render")
    public ResponseEntity<String> renderDocument(
            @RequestParam("file") MultipartFile file) {
        
        try {
            // Save uploaded file temporarily
            Path tempFile = Files.createTempFile("upload", ".tmp");
            file.transferTo(tempFile.toFile());
            
            // Render with comments
            String outputDir = renderDocumentWithComments(
                tempFile.toString(), 
                "web-output"
            );
            
            return ResponseEntity.ok("Document rendered: " + outputDir);
            
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                .body("Rendering failed: " + e.getMessage());
        }
    }
}
public class BatchDocumentProcessor {
    
    public void processFolderWithComments(String inputFolder) {
        File folder = new File(inputFolder);
        File[] files = folder.listFiles((dir, name) -> 
            name.toLowerCase().endsWith(".docx") || 
            name.toLowerCase().endsWith(".xlsx") ||
            name.toLowerCase().endsWith(".pptx")
        );
        
        if (files == null) return;
        
        for (File file : files) {
            try {
                String outputDir = file.getName().replace(".", "_") + "_output";
                renderDocumentWithComments(file.getAbsolutePath(), outputDir);
                System.out.println("✓ Processed: " + file.getName());
                
            } catch (Exception e) {
                System.err.println("❌ Failed to process " + file.getName() + ": " + e.getMessage());
            }
        }
    }
}
// Simple approach works fine
try (Viewer viewer = new Viewer(documentPath)) {
    viewer.view(viewOptions);
}
public class DocumentRenderingService {
    private final ExecutorService executorService = 
        Executors.newFixedThreadPool(4); // Limit concurrent renderings
    
    public CompletableFuture<String> renderAsync(String documentPath) {
        return CompletableFuture.supplyAsync(() -> {
            try (Viewer viewer = new Viewer(documentPath)) {
                // Rendering logic here
                return "success";
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }, executorService);
    }
}
public class CachedDocumentRenderer {
    private final Map<String, String> renderCache = new ConcurrentHashMap<>();
    
    public String renderWithCaching(String documentPath) {
        String cacheKey = generateCacheKey(documentPath);
        
        return renderCache.computeIfAbsent(cacheKey, key -> {
            // Only render if not already cached
            return performActualRendering(documentPath);
        });
    }
    
    private String generateCacheKey(String documentPath) {
        // Include file modification time in cache key
        File file = new File(documentPath);
        return documentPath + "_" + file.lastModified();
    }
}
LoadOptions loadOptions = new LoadOptions();
loadOptions.setPassword("your-password");
try (Viewer viewer = new Viewer("protected-doc.docx", loadOptions)) {
    // Render as usual
}
viewer.view(viewOptions, 1, 3, 5); // Renders only pages 1, 3, and 5
System.out.println("Starting render for: " + documentName);
long startTime = System.currentTimeMillis();
viewer.view(viewOptions);
long endTime = System.currentTimeMillis();
System.out.println("Rendering completed in: " + (endTime - startTime) + "ms");
try (Viewer viewer = new Viewer(documentPath)) {
    viewer.view(viewOptions);
} catch (CorruptOrDamagedFileException e) {
    System.err.println("Document is corrupted: " + e.getMessage());
} catch (Exception e) {
    System.err.println("General error: " + e.getMessage());
}

Связанные учебники