通过 remix 生成并下载 PDF

问题描述 投票:0回答:1

我从组件获取 HTML 并将其发送到将生成 PDF 的端点。之后我想下载生成的 PDF。

这是我用来调用端点并在正文中发送

html
的代码:

const formDataHtml = formData.get('html') as string;
const html = new URLSearchParams({ html: formDataHtml });
    
const response = await fetchApi(`/pdf/html2pdf`, {
    request,
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: html,
    shouldParseResponse: false,
    shouldStringifyBody: false,
});
    
if (!response.success) {
    return json({ error: response.error.message }, response.error.statusCode);
}
    
const pdfFileData = response.data as PdfFileData;
const pdfBuffer = await new Response(pdfFileData.body).arrayBuffer();
const pdfUint8Array = new Uint8Array(pdfBuffer);
    
return new Response(pdfUint8Array, {
    headers: {
        'Content-Type': 'application/pdf',
        'Content-Disposition': `attachment; filename=protokol.pdf`,
    },
}); 

这是触发下载的“下载 PDF”按钮:

function DownloadPDFForm({endpoint, html, children}) {
    const fetcher = useFetcher<any>();
    const downloadRef = React.useRef<HTMLAnchorElement>(null);
    const args = { html };

    React.useEffect(() => {
        const response = fetcher.data;
        if (!response) return;

        const blob = new Blob([response], { type: 'application/pdf' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'file.pdf';
        a.click();
        URL.revokeObjectURL(url);
    }, [fetcher.data]);

    function onClick() {
        const formData = new FormData();
        formData.set('endpoint', endpoint);
        formData.set('intent', 'download-pdf');
        for (const [key, value] of Object.entries(args)) formData.append(key, value);

        fetcher.submit(formData, {
            action: '/api/manage-files',
            method: 'POST',
        });
    }

    return (
        <div className={cn('flex items-center')}>
            <a className="sr-only" ref={downloadRef} href={fetcher.data?.url}>
                DOWNLOAD
            </a>
            <button type="button" onClick={onClick}>DOWNLOAD PDF</button>
        </div>
    );
} 

调用端点时,触发PDF下载,但所有页面都是空白。 formDataHtml 越大,下载的 PDF 中的页面就越多,尽管所有页面都是空白的。

注意:

formDataHtml
html
不为空,因为我对它们进行了 console.log 记录(还使用一些基本的 HTML 进行了测试)

javascript reactjs remix.run
1个回答
0
投票

我必须深入挖掘才能找到问题所在,显然是与 Remix 服务器相关的问题。我的解决方法是解码从服务器返回的 Base64 字符串:

const base64ToBuffer = (base64: string): ArrayBuffer => {
const binaryString = window.atob(base64); // Decode base64 string
const length = binaryString.length;
const bytes = new Uint8Array(new ArrayBuffer(length));

for (let i = 0; i < length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
}

return bytes.buffer;
};
© www.soinside.com 2019 - 2024. All rights reserved.