Я получаю 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.info (также протестировано с использованием базового HTML).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Мне пришлось немного покопаться, чтобы выяснить, в чем проблема, и, очевидно, это связано с сервером 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;
};