fix: add client side pdf render

This commit is contained in:
David Nguyen
2026-01-27 15:12:59 +11:00
parent 4fb3c2cb0f
commit 8186d2817f
4 changed files with 79 additions and 10 deletions
@@ -0,0 +1,73 @@
import pMap from 'p-map';
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf.mjs';
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/legacy/build/pdf.worker.min.mjs',
import.meta.url,
).toString();
export type PdfToImagesOptions = {
scale?: number;
};
export type PdfImageResult = {
pageIndex: number;
image: string;
width: number;
height: number;
};
export const pdfToImagesClientSide = async (
pdfBytes: Uint8Array,
options: PdfToImagesOptions = {},
): Promise<PdfImageResult[]> => {
const { scale = 2 } = options;
const task = pdfjsLib.getDocument({
data: pdfBytes,
});
const pdf = await task.promise;
const images = await pMap(
Array.from({ length: pdf.numPages }),
async (_, pageIndex) => {
const pageNumber = pageIndex + 1;
const page = await pdf.getPage(pageNumber);
const viewport = page.getViewport({ scale });
const canvas = document.createElement('canvas');
canvas.width = Math.floor(viewport.width);
canvas.height = Math.floor(viewport.height);
const context = canvas.getContext('2d');
if (!context) {
throw new Error('Failed to get 2D canvas context');
}
await page.render({
canvasContext: context,
viewport,
canvas,
}).promise;
const imageBase64 = canvas.toDataURL('image/jpeg');
page.cleanup();
return {
pageIndex,
image: imageBase64,
width: canvas.width,
height: canvas.height,
};
},
{ concurrency: 50 },
);
await pdf.destroy();
await task.destroy();
return images;
};
@@ -19,7 +19,7 @@ import { useVirtualList } from '../virtual-list/use-virtual-list';
import { PdfViewerErrorState, PdfViewerLoadingState } from './pdf-viewer-states';
export type OverrideImage = {
image: Buffer;
image: string;
width: number;
height: number;
};
@@ -78,7 +78,7 @@ export const PDFViewer = ({
const derivedPages = useMemo((): PageMeta[] => {
if (overrideImages) {
return overrideImages.map((image) => ({
imageUrl: `data:image/jpeg;base64,${image.image.toString('base64')}`,
imageUrl: image.image,
width: image.width,
height: image.height,
documentDataId: '',