先说需求,最近有一个需求 是 后台 把服务器上的文档转成pdf 并打印, 后来发现 java 打印不行,因为我们是一个web服务,所以 在服务器端打印不行,只能用 前端js打印。
我们遇到最大的问题就是 iframe 能显示了,但是 就是 死活不能打印 要么就是跨域问题,要么就是打印的是空白页面。然后看网上分析 各种什么 另一个页面包裹这个iframe 然后 用postMessage。
然后 找了很久 结果 发现 在一个 回答很少的地方找到了解决我们问题的方法。
下面上代码(我们前端是用react.js):
java端:
@PostMapping("/print")
public String testPdf(HttpServletRequest request, HttpServletResponse response, @RequestParam(name = "id")String docId) throws Exception{
return printerPrintWordServices.getPDFByBase64(docId);
}
就一个很简单的接口,返回一个字符串,就是pdf 转成了 字符串 这个网上有很多 ,这个需求的关键是前端。
js端:
const [blobUrl, setBlobUrl] = useState();
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i += 1) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
};
const handelPrintOk = () => {
const contentType = 'application/pdf';
const blob = b64toBlob(url, contentType);
const curBlobUrl = URL.createObjectURL(blob);
setBlobUrl(curBlobUrl);
const iframeEle = document.getElementById('my-frame');
if (iframeEle) {
iframeEle.onload = () => {
iframeEle.contentWindow.print();
};
}
};
return (
<>
<Modal
title="打印文件"
visible={showPrint.show}
onOk={handelPrintOk}
onCancel={handelPrintCancel}
okText="打印"
cancelText="取消"
width="643px"
>
<div id="pdfPrint">
<PDF
file={`data:application/pdf;base64,${url}`}
onDocumentComplete={onDocumentComplete}
page={pagination.page}
/>
<Pagination
defaultCurrent={pagination.page}
total={pagination.total}
pageSize={1}
onChange={handlePageChange}
/>
<div style={{ textAlign: 'center' }}>
<span>第{pagination.page}页</span>/<span>共{pagination.total}页</span>
</div>
</div>
<iframe name="my-frame" id="my-frame" title="my-frame" style={{ display: 'none' }} src={blobUrl} />
</Modal>
</>
);
其实关键的就是b64toBlob 方法 和 handelPrintOk 方法 利用的是 iframe。
参考文章
也是心累,我一个搞后端的 结果 帮前端解决问题。