在 Python 通过 Java 将 PowerPoint 演示文稿转换为 Markdown

概览

Aspose.Slides for Python via Java 可以将 PPT 和 PPTX 演示文稿转换为 Markdown,以用于文档、静态站点、内容迁移和版本控制工作流。您可以选择 Markdown 方言,控制幻灯片内容的渲染方式,并决定导出图像的存储位置以及生成的 Markdown 如何引用它们。

默认情况下,Markdown 导出仅使用文本输出。若要导出可视内容,请使用 MarkdownSaveOptions.setExportType 方法将导出类型设置为来自 MarkdownExportType 枚举的 SequentialVisual 值。Sequential 会分别且按顺序渲染幻灯片项目,而 Visual 则保持分组项目在一起,以保留它们的视觉关系。TextOnly 值不会生成图像资源,因此在该模式下不会调用图像保存回调。

将演示文稿转换为 Markdown

使用 Presentation 类加载源文件,然后使用 Presentation.save 方法并传入来自 SaveFormat 枚举的 Md 值。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, SaveFormat

presentation = Presentation("presentation.pptx")
try:
    presentation.save("presentation.md", SaveFormat.Md)
finally:
    presentation.dispose()

每个示例都从当前工作目录读取 presentation.pptx。在运行示例之前,请先安装 Aspose.Slides for Python via Java 以及兼容的 Java 运行时。每个 Python 进程只需启动一次 JVM。

选择 Markdown 方言

MarkdownSaveOptions.setFlavor 方法控制输出使用的 Markdown 规范。Flavor 枚举包括 CommonMark、GitHub Flavored Markdown 以及其他受支持的变体。

下面的示例将演示文稿导出为 CommonMark:

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Flavor, MarkdownSaveOptions, Presentation, SaveFormat

presentation = Presentation("presentation.pptx")
try:
    options = MarkdownSaveOptions()
    options.setFlavor(Flavor.CommonMark)

    presentation.save("presentation.md", SaveFormat.Md, options)
finally:
    presentation.dispose()

使用默认本地保存行为导出图像

MarkdownSaveOptions 类提供两种方法来配置本地保存的图像:

下面的示例渲染可视内容,将图像写入 output/assets,并在 Markdown 文档中创建相对图像引用:

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from pathlib import Path
from asposeslides.api import MarkdownExportType, MarkdownSaveOptions, Presentation, SaveFormat

output_directory = Path("output")
output_directory.mkdir(parents=True, exist_ok=True)

presentation = Presentation("presentation.pptx")
try:
    options = MarkdownSaveOptions()
    options.setExportType(MarkdownExportType.Visual)
    options.setBasePath(str(output_directory))
    options.setImagesSaveFolderName("assets")

    markdown_path = output_directory / "presentation.md"
    presentation.save(str(markdown_path), SaveFormat.Md, options)
finally:
    presentation.dispose()

当自定义图像保存处理程序返回 False 时,此行为也会作为回退使用。

自定义图像保存和 Markdown 链接

使用 MarkdownSaveOptions.setImageSaving 方法注册回调,以处理在 Markdown 导出期间产生的非 SVG 位图和元文件资源。其 MarkdownImageSavingHandler 回调接收图像对象、其 ImageFormat 值以及作为单元素 String[] 参数的生成的 Markdown 链接。使用提供的格式保存或上传图像,并将 link[0] 替换为必须出现在 Markdown 输出中的引用。

以 SVG 格式产生的资源单独处理。使用 MarkdownSaveOptions.setSvgImageSaving 方法注册回调。其 MarkdownSvgImageSavingHandler 回调接收一个 SvgImage 对象和单元素 String[] link 参数。SVG 没有 ImageFormat 参数;请改为使用 SvgImage.getSvgData 方法获取并写入或上传其 XML 数据。根据导出模式和视觉分组,源演示文稿中的 SVG 可能会被光栅化或与其他内容合并;生成的非 SVG 资源随后会传递给图像保存回调。若每个导出的视觉资源都需要自定义处理,请同时注册这两个回调。

处理程序的返回值决定由谁处理图像:

  • 返回 True 表示处理程序已保存、上传、转换或以其他方式处理图像,并已为 link[0] 赋予有效值。Aspose.Slides 将该值写入 Markdown 文档,并且不会执行默认的本地保存。
  • 返回 False 则让 Aspose.Slides 按照由 MarkdownSaveOptions.setBasePathMarkdownSaveOptions.setImagesSaveFolderName 设置的值本地保存图像并生成链接。

在 Python 中,可使用 jpype.JProxy 注册这些回调,通过实现 Java 回调接口的 invoke 方法。link 参数是可变的 Java 字符串数组:在处理之前先将 link[0] 转换为 Python 字符串,然后将替换后的 URL 赋回 link[0]

将图像保存到 CDN 源目录并使用外部 URL

下面的示例将 cdn-origin/presentations/quarterly-report 视为已挂载或同步的 CDN 源目录。每个处理程序提取生成的文件名,将图像保存到该自定义目录,并用公共 CDN URL 替换生成的本地引用。示例本身不执行网络上传:只有在目录被挂载为 CDN 源或其文件已发布到 CDN 后,URL 才会生效。若使用对象存储,请将文件系统写入替换为存储 SDK 的上传操作,并仅在上传成功后为 link[0] 赋值。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from pathlib import Path
from urllib.parse import quote
from asposeslides.api import MarkdownExportType, MarkdownSaveOptions, Presentation, SaveFormat

output_directory = Path("output")
public_base_url = "https://cdn.example.com/presentations/quarterly-report"
storage_directory = Path("cdn-origin", "presentations", "quarterly-report")
output_directory.mkdir(parents=True, exist_ok=True)
storage_directory.mkdir(parents=True, exist_ok=True)

def get_file_name(generated_link):
    normalized_link = str(generated_link).replace("\\", "/")
    return normalized_link.rsplit("/", 1)[-1]

def save_image(image, image_format, link):
    if image.getWidth() < 128 or image.getHeight() < 128:
        return False

    file_name = get_file_name(link[0])
    storage_path = storage_directory / file_name
    image.save(str(storage_path), image_format)
    encoded_file_name = quote(file_name, safe="")
    link[0] = public_base_url + "/" + encoded_file_name
    return True

def save_svg(svg_image, link):
    file_name = get_file_name(link[0])
    storage_path = storage_directory / file_name
    svg_data = svg_image.getSvgData()
    try:
        storage_path.write_bytes(bytes(svg_data))
    except OSError as error:
        print(f"Could not save the SVG image: {error}")
        return False

    encoded_file_name = quote(file_name, safe="")
    link[0] = public_base_url + "/" + encoded_file_name
    return True

image_handler = jpype.JProxy("com.aspose.slides.MarkdownSaveOptions$MarkdownImageSavingHandler", dict(invoke=save_image))
svg_handler = jpype.JProxy("com.aspose.slides.MarkdownSaveOptions$MarkdownSvgImageSavingHandler", dict(invoke=save_svg))

presentation = Presentation("presentation.pptx")
try:
    options = MarkdownSaveOptions()
    options.setExportType(MarkdownExportType.Visual)
    options.setBasePath(str(output_directory))
    options.setImagesSaveFolderName("fallback-images")
    options.setImageSaving(image_handler)
    options.setSvgImageSaving(svg_handler)

    markdown_path = output_directory / "presentation.md"
    presentation.save(str(markdown_path), SaveFormat.Md, options)
finally:
    presentation.dispose()

位图处理程序有意对小于 128 × 128 像素的图像返回 False,因此 Aspose.Slides 会使用默认行为将这些图像保存到 output/fallback-images。更大的位图、元文件资源以及 SVG 资源则由自定义代码处理。例如,生成的本地引用 fallback-images/image1.png 将变为 https://cdn.example.com/presentations/quarterly-report/image1.png。处理程序仅在写入文件时使用操作系统路径;写入 Markdown 的链接使用正斜杠并对文件名进行 URL 编码。构建相对链接时同样使用 /,而不是平台特定的目录分隔符。

常见问题

一个处理程序可以同时处理光栅图像和 SVG 图像吗?

不可以。请使用 MarkdownSaveOptions.setImageSaving 处理位图和元文件资源,使用 MarkdownSaveOptions.setSvgImageSaving 处理以 SVG 形式产生的资源。前者提供图像对象和 ImageFormat 值;后者提供可通过 SvgImage.getSvgData 读取 SVG 数据的 SvgImage 对象。导出期间被光栅化的源 SVG 将通过图像保存回调进行处理。

当图像保存处理程序返回 False 时会发生什么?

Aspose.Slides 将使用默认的本地保存行为。图像的位置和生成的引用由使用 MarkdownSaveOptions.setBasePathMarkdownSaveOptions.setImagesSaveFolderName 设置的值控制。

处理程序可以在不本地保存图像的情况下提供 URL 吗?

可以。处理程序可以将图像上传到对象存储或传递给其他服务,为 link[0] 赋予生成的 URL,并返回 True。处理程序必须自行完成所有处理;返回 True 会阻止默认的本地保存。

为什么 Markdown 导出会因处理程序抛出 InvalidOperationException

当处理程序返回 True 但未提供有效链接时会出现此异常。请在返回 True 之前为 link[0] 赋予应写入 Markdown 的相对路径或外部 URL。

图像链接应使用哪种路径分隔符?

在 Markdown 链接和 URL 中使用正斜杠 /。仅在文件系统路径中使用 pathlib.Path,然后单独构建或规范化 Markdown 引用。

Markdown 导出时会保留超链接吗?

会。文本 hyperlinks 会保留为标准的 Markdown 链接。幻灯片 transitionsanimations 则不会被转换。

可以并行将演示文稿转换为 Markdown 吗?

可以并行处理不同的演示文稿文件,但不要在多个线程之间共享同一个 Presentation 实例。请遵循 multithreading guidelines 并为每个文件使用独立的实例。