Преобразовать презентации PowerPoint в HTML на Android

Обзор

Aspose.Slides for Android via Java может сохранять презентации PowerPoint в HTML без Microsoft PowerPoint. Базовое преобразование состоит из одиночной загрузки Presentation и вызова save с SaveFormat. Используйте HtmlOptions когда нужно контролировать экспортируемый макет, шрифты, изображения, заметки, комментарии, вывод SVG или связанные ресурсы.

Это руководство сосредоточено на практических сценариях экспорта HTML:

  • Экспортировать всю презентацию или выбранные слайды.
  • Создавать HTML с фиксированным макетом, адаптивный или основанный на SVG.
  • Включать примечания докладчика и комментарии.
  • Контролировать качество изображений и данные об обрезанных изображениях.
  • Встраивать шрифты или сохранять файлы шрифтов отдельно.
  • Выбирать способ записи и ссылки на внешние ресурсы и медиафайлы.

По умолчанию экспорт HTML создает автономный HTML‑документ, где большинство ресурсов встроено. Это удобно для распространения одного файла, но может увеличить размер вывода. Для веб‑публикации рассмотрите внешние ресурсы, снижение DPI изображений и встраивание только тех шрифтов, которые недоступны в целевой среде.

Конвертировать презентацию в HTML

Чтобы экспортировать презентацию в HTML, загрузите её с помощью Presentation и сохраните её с помощью SaveFormat.Html.

Presentation presentation = new Presentation("presentation.pptx");
try {
    presentation.save("presentation.html", SaveFormat.Html);
} finally {
    presentation.dispose();
}

В этом примере записывается один HTML‑файл. Объект презентации освобождается в блоке finally, что закрывает файловые дескрипторы и ресурсы рендеринга после экспорта.

Использовать HtmlOptions

HtmlOptions — основной класс конфигурации экспорта HTML. Часто используемые параметры включают:

  • SlidesLayoutOptions: добавляет заметки, комментарии, раздаточные материалы или другую информацию о макете.
  • HtmlFormatter: изменяет структуру HTML‑документа или делегирует форматирование контроллеру.
  • SlideImageFormat: изменяет способ представления слайдов, например как SVG.
  • PicturesCompression: управляет DPI изображений и размером вывода.
  • DeletePicturesCroppedAreas: сохраняет или удаляет данные об обрезанных изображениях.
  • SvgResponsiveLayout: заставляет экспортированный SVG‑контент адаптироваться к своему контейнеру.
  • ShowHiddenSlides: включает скрытые слайды при необходимости.

В следующих разделах показаны самые распространённые параметры отдельно, чтобы вы могли комбинировать только те, которые нужны вашему workflow.

Конвертировать выбранные слайды в HTML

Перегрузка Presentation.save, принимающая номера слайдов, использует нумерацию, начинающуюся с 1. Цикл ниже сохраняет каждый слайд в отдельный HTML‑файл.

Presentation presentation = new Presentation("presentation.pptx");
try {
    int slideCount = presentation.getSlides().size();

    for (int slideIndex = 0; slideIndex < slideCount; slideIndex++) {
        int slideNumber = slideIndex + 1;
        int[] slideNumbers = { slideNumber };
        String htmlFileName = "slide-" + slideNumber + ".html";

        presentation.save(htmlFileName, slideNumbers, SaveFormat.Html);
    }
} finally {
    presentation.dispose();
}

Используйте этот шаблон, когда веб‑сайт или приложение требует одну HTML‑страницу на каждый слайд. Если каждый слайд должен иметь одинаковый макет, создайте один экземпляр HtmlOptions и передайте его каждому вызову save.

Создать адаптивный HTML

ResponsiveHtmlController предоставляет адаптивный HTML‑вывод через HtmlFormatter. Используйте его, когда экспортированная страница должна лучше адаптироваться к ширине браузера.

Presentation presentation = new Presentation("presentation.pptx");
try {
    ResponsiveHtmlController controller = new ResponsiveHtmlController();
    HtmlFormatter formatter = HtmlFormatter.createCustomFormatter(controller);

    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setHtmlFormatter(formatter);

    presentation.save("presentation-responsive.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

Для адаптивного макета на основе SVG задайте SvgResponsiveLayout в HtmlOptions. Это полезно, когда содержимое слайда экспортируется как масштабируемая SVG‑разметка.

Presentation presentation = new Presentation("presentation.pptx");
try {
    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setSvgResponsiveLayout(true);

    presentation.save("presentation-svg-responsive.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

Включить примечания докладчика и комментарии

Используйте NotesCommentsLayoutingOptions через HtmlOptions.SlidesLayoutOptions, чтобы включить примечания докладчика или комментарии. По умолчанию заметки и комментарии скрыты, если только вы не зададите их позиции.

Предположим, исходная презентация содержит примечания докладчика:

Слайд с примечаниями докладчика в PowerPoint

Следующий код экспортирует содержимое слайда с примечаниями докладчика под слайдом.

Presentation presentation = new Presentation("presentation.pptx");
try {
    NotesCommentsLayoutingOptions layoutOptions = new NotesCommentsLayoutingOptions();
    layoutOptions.setNotesPosition(NotesPositions.BottomFull);

    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setSlidesLayoutOptions(layoutOptions);

    presentation.save("presentation-with-notes.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

Экспортированный HTML включает область заметок:

HTML‑вывод со слайдом и примечаниями докладчика

Чтобы экспортировать комментарии, задайте CommentsPosition, например CommentsPositions.Right или CommentsPositions.Bottom. Если нужны только комментарии, опустите NotesPosition. Если нужны и заметки, и комментарии — задайте оба свойства.

Контролировать качество изображений и обрезанные области

Экспорт HTML может сжимать изображения слайдов для уменьшения размера вывода. Установите PicturesCompression в значение из PicturesCompression, когда требуется более высокое качество изображения.

Presentation presentation = new Presentation("presentation.pptx");
try {
    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setPicturesCompression(PicturesCompression.Dpi150);

    presentation.save("presentation-dpi-150.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

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

Presentation presentation = new Presentation("presentation.pptx");
try {
    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setDeletePicturesCroppedAreas(false);

    presentation.save("presentation-with-cropped-areas.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

Добавить CSS

Для простого стилизования передайте строку CSS в HtmlFormatter.createDocumentFormatter. Это изменяет окружающий HTML‑документ, пока Aspose.Slides продолжает рендерить содержимое слайдов.

Presentation presentation = new Presentation("presentation.pptx");
try {
    String cssRules = "body { margin: 0; background: #f7f7f7; } .slide { margin: 24px auto; }";
    HtmlFormatter formatter = HtmlFormatter.createDocumentFormatter(cssRules, true);

    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setHtmlFormatter(formatter);

    presentation.save("presentation-styled.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

Для пользовательского заголовка документа, подключённого CSS‑файла или пользовательской разметки вокруг слайдов и фигур реализуйте IHtmlFormattingController и передайте его в HtmlFormatter через createCustomFormatter.

Встраивание шрифтов

Если в целевой среде шрифты презентации могут быть не установлены, встраивайте шрифты в HTML с помощью EmbedAllFontsHtmlController. Встраивание повышает визуальное соответствие, но увеличивает размер вывода.

Presentation presentation = new Presentation("presentation.pptx");
try {
    String[] fontNamesToExclude = { "Arial", "Calibri" };
    EmbedAllFontsHtmlController fontController = new EmbedAllFontsHtmlController(fontNamesToExclude);
    HtmlFormatter formatter = HtmlFormatter.createCustomFormatter(fontController);

    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setHtmlFormatter(formatter);

    presentation.save("presentation-embedded-fonts.html", SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

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

Ссылка на файлы шрифтов вместо их встраивания

Чтобы уменьшить размер HTML‑файла, можно записать данные шрифтов в отдельные файлы WOFF и добавить правила @font-face в HTML. Ниже приведён помощник, расширяющий EmbedAllFontsHtmlController и переопределяющий writeFont.

class LinkedFontsHtmlController extends EmbedAllFontsHtmlController {
    private final String fontOutputDirectory;
    private final String fontUrlPrefix;

    LinkedFontsHtmlController(
            String fontOutputDirectory,
            String fontUrlPrefix) throws java.io.IOException {
        super(new String[0]);
        this.fontOutputDirectory = fontOutputDirectory;
        this.fontUrlPrefix = fontUrlPrefix.endsWith("/") ? fontUrlPrefix : fontUrlPrefix + "/";
        
        File dirs = new File(fontOutputDirectory);
        dirs.mkdirs();
    }

    @Override
    public void writeFont(
            IHtmlGenerator generator,
            IFontData originalFont,
            IFontData substitutedFont,
            String fontStyle,
            String fontWeight,
            byte[] fontData) {
        try {
            IFontData font = substitutedFont == null ? originalFont : substitutedFont;
            String safeFontName = makeSafeFileName(font.getFontName());
            String safeFontStyle = fontStyle == null || fontStyle.trim().isEmpty() ? "normal" : fontStyle;
            String safeFontWeight = fontWeight == null || fontWeight.trim().isEmpty() ? "normal" : fontWeight;
            String fontFileName = safeFontName + "-" + safeFontStyle + "-" + safeFontWeight + ".woff";
            String fontFilePath = fontOutputDirectory + "/" + fontFileName;

            FileOutputStream fos = new FileOutputStream(fontFilePath);
            fos.write(fontData);
            fos.close();

            String encodedFontFileName = java.net.URLEncoder.encode(fontFileName, "UTF-8");
            String fontUrl = fontUrlPrefix + encodedFontFileName.replace("+", "%20");
            String escapedBackslashes = font.getFontName().replace("\\", "\\\\");
            String fontFamily = escapedBackslashes.replace("'", "\\'");

            generator.addHtml("<style>");
            generator.addHtml("@font-face {");
            generator.addHtml("font-family: '" + fontFamily + "';");
            generator.addHtml("font-style: " + safeFontStyle + ";");
            generator.addHtml("font-weight: " + safeFontWeight + ";");
            generator.addHtml("src: url('" + fontUrl + "') format('woff');");
            generator.addHtml("}");
            generator.addHtml("</style>");
        } catch (java.io.IOException exception) {
            throw new RuntimeException("Unable to write an exported font.", exception);
        }
    }

    private String makeSafeFileName(String fileName) {
        String invalidCharacters = "\\/:*?\"<>|";
        char[] safeCharacters = fileName.toCharArray();

        for (int characterIndex = 0; characterIndex < safeCharacters.length; characterIndex++) {
            if (invalidCharacters.indexOf(safeCharacters[characterIndex]) >= 0) {
                safeCharacters[characterIndex] = '_';
            }
        }

        return new String(safeCharacters);
    }
}

String outputDirectory = System.getProperty("user.dir") + "/html-output";
String fontsDirectory = outputDirectory + "/fonts";
File dir = new File("path/to/folder");
dir.mkdir();

Presentation presentation = new Presentation("presentation.pptx");
try {
    LinkedFontsHtmlController fontController = new LinkedFontsHtmlController(fontsDirectory, "fonts");
    HtmlFormatter formatter = HtmlFormatter.createCustomFormatter(fontController);

    HtmlOptions htmlOptions = new HtmlOptions();
    htmlOptions.setHtmlFormatter(formatter);

    String htmlFilePath = outputDirectory + "/presentation.html";
    presentation.save(htmlFilePath.toString(), SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

В этом примере файлы шрифтов сохраняются в html-output/fonts, а HTML ссылается на них по URL‑ам вроде fonts/BrandFont-normal-400.woff. Если HTML‑файл и шрифты развернуты в другом месте, выберите fontUrlPrefix, чтобы он соответствовал пути развернутого URL.

Сохранить ресурсы внешне

Автономный HTML легко перемещать, но встроенные ресурсы Base64 могут сделать файл громоздким. Если вашему приложению нужны внешние файлы изображений, реализуйте ILinkEmbedController и передайте его в конструктор HtmlOptions.

При внешнем размещении ресурсов выбирайте два пути преднамеренно:

  • Путь вывода в файловой системе, куда приложение записывает сгенерированные изображения, шрифты, аудио или видео.
  • Путь URL, который браузер использует из HTML‑документа для загрузки этих файлов.

Экспорт медиафайлов

VideoPlayerHtmlController экспортирует видео и аудио файлы и записывает HTML, который может воспроизводить их в браузере. Его конструктор принимает:

  • path: каталог, в который будут записываться сгенерированные медиафайлы.
  • fileName: имя генерируемого HTML‑файла.
  • baseUri: абсолютный URI‑префикс, используемый в ссылках HTML на медиафайлы.

Если HTML‑файл находится по пути html-output/presentation.html, а медиафайлы сохраняются в html-output/media, path должен указывать на каталог медиа на диске, тогда как baseUri должен указывать на тот же каталог с точки зрения браузера. Для локального предварительного просмотра можно собрать URI file:/// из каталога медиа. Для развернутого приложения используйте абсолютный URL опубликованного каталога медиа.

String outputDirectory = System.getProperty("user.dir") + "/html-output";
String mediaDirectory = outputDirectory + "/media";
File outDir = new File(outputDirectory);
outDir.mkdir();
File mediaDir = new File(mediaDirectory);
mediaDir.mkdir();

String htmlFileName = "presentation.html";
String mediaBaseUri = mediaDirectory;

Presentation presentation = new Presentation();
try {
    byte[] videoData = ...; // intro.mp4 (вводный ролик)

    IVideo video = presentation.getVideos().addVideo(videoData);
    ISlide slide = presentation.getSlides().get_Item(0);
    slide.getShapes().addVideoFrame(20, 20, 480, 270, video);

    String mediaDirectoryPath = mediaDirectory;
    VideoPlayerHtmlController controller = new VideoPlayerHtmlController(mediaDirectoryPath, htmlFileName, mediaBaseUri);
    HtmlFormatter formatter = HtmlFormatter.createCustomFormatter(controller);
    SVGOptions svgOptions = new SVGOptions(controller);
    SlideImageFormat slideImageFormat = SlideImageFormat.svg(svgOptions);

    HtmlOptions htmlOptions = new HtmlOptions(controller);
    htmlOptions.setHtmlFormatter(formatter);
    htmlOptions.setSlideImageFormat(slideImageFormat);

    String htmlFilePath = outputDirectory + "/" + htmlFileName;
    presentation.save(htmlFilePath.toString(), SaveFormat.Html, htmlOptions);
} finally {
    presentation.dispose();
}

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

Производительность и управление ресурсами

Преобразование в HTML — это операция рендеринга, поэтому время обработки и использование памяти зависят от количества слайдов, разрешения изображений, шрифтов, эффектов, диаграмм и встроенных медиа. Более высокие значения DPI в PicturesCompression, встроенные шрифты, вывод SVG и сохранённые обрезанные области изображений могут повысить точность, но обычно увеличивают размер вывода.

Для пакетного преобразования:

  • Сразу освобождайте каждый экземпляр Presentation.
  • Используйте отдельные каталоги вывода для разных задач.
  • Избегайте встраивания распространённых шрифтов, если это не требуется для точности.
  • Снижайте DPI изображений, когда HTML нужен для предварительного просмотра или миниатюр.
  • Храните исходную презентацию, сгенерированный HTML и внешние ресурсы совместно до окончательного определения путей развертывания.

FAQ

Сохраняются ли гиперссылки в HTML‑выводе?

Да. Гиперссылки презентации экспортируются в HTML и остаются кликабельными, если целевой URL действителен.

Могу ли я конвертировать презентации в HTML параллельно?

Да, но не используйте один экземпляр Presentation в разных потоках. Обрабатывайте разные файлы отдельными экземплярами презентаций, отдельными потоками и отдельными каталогами вывода. См. руководство по multithreading для деталей.

Является ли объект Presentation потокобезопасным?

Нет. Один экземпляр Presentation должен быть загружен, изменён, сохранён и освобождён в одном потоке. Для параллельной работы создавайте независимый экземпляр на каждый поток или процесс.

Почему генерируемый HTML‑файл большой?

Экспорт по умолчанию может встраивать ресурсы непосредственно в HTML. Встроенные шрифты, изображения с высоким DPI, медиа, SVG‑контент и сохранённые обрезанные области изображений также увеличивают размер. Используйте внешние ресурсы, исключайте общие шрифты из встраивания и уменьшайте PicturesCompression, когда меньший размер важнее максимального качества.

Как выбрать baseUri при экспорте медиа?

Выбирайте baseUri с точки зрения браузера и передавайте его как абсолютный URI. Для локального предварительного просмотра его можно получить из каталога вывода через mediaDirectory.toUri().toString(). Для развертывания используйте абсолютный URL опубликованного каталога медиа. Файловая система path и браузерный baseUri не обязаны быть одинаковой строкой, но оба должны описывать одно и то же расположение ресурса.

Могу ли я включать скрытые слайды?

Да. Установите ShowHiddenSlides в true на HtmlOptions, когда скрытые слайды должны быть экспортированы.