Skip to content

截图工具 (Snapshot)

福昕 PDF SDK(Web) 提供截图工具,开发者可以截取 PDF 页面中的指定区域,并将截图图片用于预览、上传、复制到剪贴板或接入自定义业务流程。

截图能力主要包含三部分:

  • 通过 PDFPageRender.getSnapshot()PDFViewer.takeSnapshot() 获取指定区域的图片数据。
  • 通过 PDFViewer.uploadImage()SnapshotServer 上传截图图片并生成可访问的图片地址。
  • 通过 PDFViewer.copySnapshot() 将截图复制到系统剪贴板。

截图接口

通过页面渲染对象截图

PDFPageRender.getSnapshot(left, top, width, height) 用于截取当前页面渲染对象上的指定区域。

javascript
const pageRender = pdfViewer.getPDFPageRender(pageIndex);

if (pageRender) {
    const imageBlob = await pageRender.getSnapshot(left, top, width, height);
    // 获取指定页面区域的图片数据。
}

通过 Viewer 截图

PDFViewer.takeSnapshot(pageIndex, left, top, width, height) 用于直接截取指定页面上的区域。pageIndex0 开始。

javascript
const imageBlob = await pdfViewer.takeSnapshot(pageIndex, left, top, width, height);
// 获取指定页面区域的图片数据。

坐标参数

lefttopwidthheight 都使用 device pixels,表示页面左上角开始的设备像素坐标和区域大小。

参数说明
pageIndex页面索引,从 0 开始。
left截图区域左上角相对页面左上角的 X 轴偏移,单位为 device pixels。
top截图区域左上角相对页面左上角的 Y 轴偏移,单位为 device pixels。
width截图区域宽度,单位为 device pixels。
height截图区域高度,单位为 device pixels。

如果业务中使用的是 PDF 坐标,需要先转换为页面渲染使用的设备像素坐标。可以参考 API Reference 中的 PDFPage.getDevicePoint()PDFPageRender.transformPoint() 等坐标转换接口。

复制截图到剪贴板

PDFViewer.copySnapshot(dataURL) 用于将图片复制到系统剪贴板。该接口接收图片地址或 Data URL 字符串,不应直接传入 Blob

下面示例将截图得到的 Blob 转换为 Data URL 后复制:

javascript
function blobToDataURL(blob) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(blob);
    });
}

button.addEventListener('click', async () => {
    const imageBlob = await pdfViewer.takeSnapshot(0, 0, 0, 200, 200);
    const dataURL = await blobToDataURL(imageBlob);
    const copied = await pdfViewer.copySnapshot(dataURL);

    if (copied) {
        console.log('截图已复制到剪贴板');
    }
});

注意

受浏览器安全策略限制,复制剪贴板通常需要在用户触发的短时事件处理函数内调用,例如按钮点击事件。剪贴板访问还需要 HTTPS 或 localhost 等安全来源。

图片存储服务

上传截图图片

PDFViewer.uploadImage(blob) 用于通过截图图片存储服务上传图片,并返回可访问的图片 URL。

javascript
const imageBlob = await pdfViewer.takeSnapshot(0, 0, 0, 200, 200);
const imageURL = await pdfViewer.uploadImage(imageBlob);

console.log('截图图片地址:', imageURL);

上传服务适用于以下场景:

  • 将截图保存到业务服务器。
  • 获取同源图片 URL,避免部分浏览器对跨源图片或剪贴板操作的限制。
  • 将截图图片地址写入业务数据或发送给其他系统。

默认图片存储服务

SDK 内置 SnapshotServer,可通过 viewerOptions.snapshotServer 修改上传行为。

javascript
const SnapshotServer = PDFViewCtrl.SnapshotServer;

const pdfui = new PDFUI({
    viewerOptions: {
        snapshotServer: new SnapshotServer({
            origin: location.origin,
            uploadSnapshotAPIPath: 'snapshot/upload',
            payloadFieldName: 'file',
            method: 'POST',
            render: function (responseText) {
                return responseText;
            }
        })
    },
    renderTo: document.body
});

SnapshotServer 常用配置如下:

配置项说明
origin服务域名。
uploadSnapshotAPIPath上传接口路径。
payloadFieldName上传表单字段名,默认值为 file
method请求方法,支持 POSTPUT
render(responseText)解析服务端响应,返回最终图片 URL。

提示

如果服务端返回格式为 { success: true, data: { url: '/snapshot/image/xxx' } },可以在 render 中解析并返回 data.url

javascript
const snapshotServer = new SnapshotServer({
    uploadSnapshotAPIPath: 'snapshot/upload',
    render: function (responseText) {
        const result = JSON.parse(responseText);
        return result.data.url;
    }
});

自定义图片存储服务

如果需要添加自定义请求头、鉴权逻辑、上传前校验或特殊响应解析,可以实现自定义 snapshotServer 对象。

javascript
const pdfui = new PDFUI({
    viewerOptions: {
        snapshotServer: {
            render(responseText) {
                const result = JSON.parse(responseText);
                return result.url;
            },
            uploadImage(imageBlob) {
                const formData = new FormData();
                formData.append('file', imageBlob, 'snapshot.png');

                return fetch('/snapshot/upload', {
                    method: 'POST',
                    headers: {
                        Authorization: `Bearer ${token}`
                    },
                    body: formData
                })
                    .then(response => response.text())
                    .then(responseText => this.render(responseText));
            }
        }
    },
    renderTo: document.body
});

截图工具 UI 入口

如果使用 UIExtension,SDK 已提供截图工具的预配置组件:

  • <snapshot-button>:普通按钮形式的截图入口。
  • <snapshot-ribbon-button>:Ribbon 按钮形式的截图入口,8.2.0 起推荐使用。
  • states:SnapshotToolController:切换当前 state-handler 为 STATE_HANDLER_SNAPSHOT_TOOL

可以在自定义布局模板中直接添加截图按钮:

html
<snapshot-ribbon-button></snapshot-ribbon-button>

也可以使用等价的基础组件和控制器:

html
<ribbon-button
    text="toolbar.buttons.snapshot"
    @controller="states:SnapshotToolController"
    @tooltip
    tooltip-title="toolbar.buttons.snapshot"
    name="snapshot-button"
    icon-class="fv__icon-toolbar-snapshot"
>toolbar.buttons.snapshot
</ribbon-button>

更多组件用法请参考 预配置业务组件

完整示例

javascript
const SnapshotServer = PDFViewCtrl.SnapshotServer;

function blobToDataURL(blob) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(blob);
    });
}

const pdfui = new PDFUI({
    viewerOptions: {
        snapshotServer: new SnapshotServer({
            origin: location.origin,
            uploadSnapshotAPIPath: 'snapshot/upload',
            payloadFieldName: 'file',
            method: 'POST',
            render: function (responseText) {
                return responseText;
            }
        })
    },
    renderTo: document.body
});

const pdfViewer = await pdfui.getPDFViewer();

document.querySelector('#copy-snapshot').addEventListener('click', async () => {
    try {
        // 截取第 1 页左上角 200 x 200 的区域。
        const imageBlob = await pdfViewer.takeSnapshot(0, 0, 0, 200, 200);

        // 上传到业务服务。
        const imageURL = await pdfViewer.uploadImage(imageBlob);
        console.log('截图图片地址:', imageURL);

        // 复制到剪贴板。
        const dataURL = await blobToDataURL(imageBlob);
        const copied = await pdfViewer.copySnapshot(dataURL);

        if (!copied) {
            console.warn('截图复制失败');
        }
    } catch (error) {
        console.error('截图处理失败:', error);
    }
});

注意事项

  • getSnapshot()takeSnapshot() 截取的是页面渲染区域,不会修改 PDF 文档内容。
  • 截图区域参数使用 device pixels,不是 PDF 坐标。
  • 较大的截图区域可能产生较大的图片数据,应根据业务场景控制截图范围。
  • copySnapshot() 受浏览器剪贴板权限和安全来源限制,建议在用户点击事件中调用。
  • PDFPageRender.getSnapshot() 属于浏览器端渲染能力,不支持 Server 环境。