使用 JS/TS 从二进制字符串创建和下载 PDF 文件
Create and Download PDF file from binary string with JS/TS
Axios 请求服务器以二进制字符串形式响应 PDF 的内容。
export const fetchPDFfile = async (id: string): Promise<string> => {
const { data } = await http.get<string>(`${baseUrl}/${id}.pdf`);
return data;
};
Chrome devtools 中的响应以及控制台记录数据如下:
%PDF-1.4
%âãÏÓ
2 0 obj <</ColorSpa ......
..........
startxref
10991
%%EOF
- 将
string
定义为 Axios 响应主体的预期类型,对吗?或者它应该是(投射到)Blob?
现在我想在客户端将其下载为 PDF 文件。有很多关于此的问题,但 none 对我有用并且 none 也有明确的答案。
到目前为止我所做的是(在 React 组件中):
const data = await fetchPDFfile(props.id);
const blob = new Blob([data], { type: 'application/pdf' });
const href = window.URL.createObjectURL(blob);
const theLink = document.createElement('a');
theLink.href = href;
theLink.download = props.id + '.pdf';
document.body.appendChild(theLink);
theLink.click();
document.body.removeChild(theLink);
这将下载一个包含 3 个空白页的 PDF 文件。页数正确,原始文档应为 3 页。但是我看到了白皮书。
const href = window.URL.createObjectURL(data); // istead of blob
抛出错误。
我应该如何转换和下载此 PDF 文件?总的来说,是需要上面的过程,还是直接从服务器下载呢? (类似于 cordova-plugin-file-transfer 所做的事情)
首先使用 Blob
作为 Promise
的通用参数。
我将使用 fetch API,因为它很容易测试。
fetch('https://www.jianjunchen.com/papers/CORS-USESEC18.slides.pdf').then(x => x.blob()).then(b => console.log(b.type))
这将记录 "application/pdf" 文件是真正的 pdf。
如果您有一个非 PDF 的 blob,并且您将其重新包装为 pdf 类型的 Blob,您可能会破坏数据。如果你得到一个真正的 string
并且你将它转换为 pdf 类型的 Blob 文件将被破坏,因为 PDF 将无效。
如果您想知道 b
是否真的是 blob
只是 console.log(b instanceof Blob)
,它应该是 true
。如果您确实收到了一个 blob,则不必像在 new Blob([data])
中那样创建新的 blob。
这个例子工作得很好:
fetch('https://www.jianjunchen.com/papers/CORS-USESEC18.slides.pdf').then(x => x.blob()).then(b => {
const url = window.URL.createObjectURL(b);
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = url;
a.download = "a.pdf";
a.click();
window.URL.revokeObjectURL(url);
})
抱歉,代码样式损坏,但我无法正确粘贴。
场景
您希望在用户单击 link 时下载文件。
解决方案 1-
直接把link
放在<a>
标签里。
缺点 - 如果出现问题,错误消息无法显示在屏幕上。
所以它导致下一个解决方案。
解决方案 2-
点击 URL 作为 API 并在收到成功消息后下载文件。
为此,我使用 File-server.js
**在发出请求时不要忘记设置{responseType: 'blob'}
http.get<string>(`${baseUrl}/${id}.pdf`, {responseType: 'blob'})
因为我们不想要 Content-Type: application/json
的响应
示例代码:
import FileSaver from 'file-saver';
downloadPdf() {
var blob = new Blob([data], {type: "application/pdf"});
FileSaver.saveAs(blob, "filename");
}
Axios 请求服务器以二进制字符串形式响应 PDF 的内容。
export const fetchPDFfile = async (id: string): Promise<string> => {
const { data } = await http.get<string>(`${baseUrl}/${id}.pdf`);
return data;
};
Chrome devtools 中的响应以及控制台记录数据如下:
%PDF-1.4
%âãÏÓ
2 0 obj <</ColorSpa ......
..........
startxref
10991
%%EOF
- 将
string
定义为 Axios 响应主体的预期类型,对吗?或者它应该是(投射到)Blob?
现在我想在客户端将其下载为 PDF 文件。有很多关于此的问题,但 none 对我有用并且 none 也有明确的答案。
到目前为止我所做的是(在 React 组件中):
const data = await fetchPDFfile(props.id);
const blob = new Blob([data], { type: 'application/pdf' });
const href = window.URL.createObjectURL(blob);
const theLink = document.createElement('a');
theLink.href = href;
theLink.download = props.id + '.pdf';
document.body.appendChild(theLink);
theLink.click();
document.body.removeChild(theLink);
这将下载一个包含 3 个空白页的 PDF 文件。页数正确,原始文档应为 3 页。但是我看到了白皮书。
const href = window.URL.createObjectURL(data); // istead of blob
抛出错误。
我应该如何转换和下载此 PDF 文件?总的来说,是需要上面的过程,还是直接从服务器下载呢? (类似于 cordova-plugin-file-transfer 所做的事情)
首先使用 Blob
作为 Promise
的通用参数。
我将使用 fetch API,因为它很容易测试。
fetch('https://www.jianjunchen.com/papers/CORS-USESEC18.slides.pdf').then(x => x.blob()).then(b => console.log(b.type))
这将记录 "application/pdf" 文件是真正的 pdf。
如果您有一个非 PDF 的 blob,并且您将其重新包装为 pdf 类型的 Blob,您可能会破坏数据。如果你得到一个真正的 string
并且你将它转换为 pdf 类型的 Blob 文件将被破坏,因为 PDF 将无效。
如果您想知道 b
是否真的是 blob
只是 console.log(b instanceof Blob)
,它应该是 true
。如果您确实收到了一个 blob,则不必像在 new Blob([data])
中那样创建新的 blob。
这个例子工作得很好:
fetch('https://www.jianjunchen.com/papers/CORS-USESEC18.slides.pdf').then(x => x.blob()).then(b => {
const url = window.URL.createObjectURL(b);
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = url;
a.download = "a.pdf";
a.click();
window.URL.revokeObjectURL(url);
})
抱歉,代码样式损坏,但我无法正确粘贴。
场景
您希望在用户单击 link 时下载文件。
解决方案 1-
直接把link
放在<a>
标签里。
缺点 - 如果出现问题,错误消息无法显示在屏幕上。
所以它导致下一个解决方案。
解决方案 2-
点击 URL 作为 API 并在收到成功消息后下载文件。 为此,我使用 File-server.js
**在发出请求时不要忘记设置{responseType: 'blob'}
http.get<string>(`${baseUrl}/${id}.pdf`, {responseType: 'blob'})
因为我们不想要 Content-Type: application/json
示例代码:
import FileSaver from 'file-saver';
downloadPdf() {
var blob = new Blob([data], {type: "application/pdf"});
FileSaver.saveAs(blob, "filename");
}