Skip to content

Commit b29a31d

Browse files
committed
fix: make PDF rendering more resilient
1 parent 0773d2d commit b29a31d

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

packages/form-js-viewer/src/render/components/form-fields/DocumentPreview.js

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,62 @@ function useValidDocumentData(dataSource) {
156156
return data.filter(isValidDocument);
157157
}
158158

159+
/**
160+
* @param {Object} props
161+
* @param {string} props.url
162+
* @param {string} props.fileName
163+
* @param {Function} props.onError
164+
* @param {string} props.errorMessageId
165+
* @returns {import("preact").JSX.Element}
166+
*/
167+
function PdfRenderer(props) {
168+
const { url, onError, errorMessageId } = props;
169+
/** @type {ReturnType<typeof import("preact/hooks").useState<null | string>>} */
170+
const [pdfObjectUrl, setPdfObjectUrl] = useState(null);
171+
const [hasError, setHasError] = useState(false);
172+
173+
useEffect(() => {
174+
/** @type {null | string} */
175+
let objectUrl = null;
176+
177+
const fetchPdf = async () => {
178+
try {
179+
const response = await fetch(url);
180+
181+
if (!response.ok) {
182+
setHasError(true);
183+
onError();
184+
return;
185+
}
186+
187+
const blob = await response.blob();
188+
objectUrl = URL.createObjectURL(blob);
189+
setPdfObjectUrl(objectUrl);
190+
} catch {
191+
setHasError(true);
192+
onError();
193+
}
194+
};
195+
196+
fetchPdf();
197+
198+
return () => {
199+
if (objectUrl) {
200+
URL.revokeObjectURL(objectUrl);
201+
}
202+
};
203+
}, [url, onError]);
204+
205+
return (
206+
<>
207+
{pdfObjectUrl !== null ? (
208+
<embed src={pdfObjectUrl} type="application/pdf" class={`fjs-${type}-pdf-viewer`} />
209+
) : null}
210+
{hasError ? <Errors id={errorMessageId} errors={['Unable to download document']} /> : null}
211+
</>
212+
);
213+
}
214+
159215
/**
160216
*
161217
* @param {Object} props
@@ -207,8 +263,12 @@ function DocumentRenderer(props) {
207263
class={singleDocumentContainerClassName}
208264
style={{ maxHeight }}
209265
aria-describedby={hasError ? errorMessageId : undefined}>
210-
<embed src={fullUrl} type="application/pdf" class={`fjs-${type}-pdf-viewer`} />
211-
{hasError ? <Errors id={errorMessageId} errors={[errorMessage]} /> : null}
266+
<PdfRenderer
267+
url={fullUrl}
268+
fileName={metadata.fileName}
269+
onError={() => setHasError(true)}
270+
errorMessageId={errorMessageId}
271+
/>
212272
</div>
213273
);
214274
}

0 commit comments

Comments
 (0)