如何将REST控制器中Jasper Reports生成的Base64 PDF传输至Ionic 3应用并打开
实现Ionic 3加载后端Base64格式PDF的方案
我来给你梳理几个实现这个需求的靠谱方案,分后端和前端两部分来说明:
一、后端REST控制器处理(Jasper Reports转PDF再转Base64)
假设你用Java Spring Boot作为后端,这里给个核心代码示例(其他后端语言逻辑类似,都是先生成PDF二进制数据再编码为Base64):
@GetMapping("/generate-pdf-base64") public ResponseEntity<String> generatePdfAsBase64() throws JRException, IOException { // 1. 加载Jasper报表模板并填充参数 InputStream jasperStream = getClass().getResourceAsStream("/reports/your-report.jasper"); Map<String, Object> parameters = new HashMap<>(); // 这里填充你的报表参数,比如数据源、自定义参数等 // 2. 生成PDF字节数组 JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parameters, new JREmptyDataSource()); byte[] pdfBytes = JasperExportManager.exportReportToPdf(jasperPrint); // 3. 转成Base64字符串返回 String base64Pdf = Base64.getEncoder().encodeToString(pdfBytes); return ResponseEntity.ok(base64Pdf); }
二、前端Ionic 3的几种实现方案
方案1:直接在WebView中打开(无需保存文件)
利用Ionic的InAppBrowser插件直接打开Base64格式的PDF,不用先存本地文件,步骤如下:
- 安装对应版本的插件(Ionic 3要适配@4版本的Native插件):
ionic cordova plugin add cordova-plugin-inappbrowser npm install @ionic-native/in-app-browser@4
- 代码实现:
import { InAppBrowser } from '@ionic-native/in-app-browser'; import { HttpClient } from '@angular/common/http'; constructor(private iab: InAppBrowser, private http: HttpClient) {} openPdfFromBase64() { this.http.get('http://你的后端接口地址/generate-pdf-base64', { responseType: 'text' }).subscribe(base64Data => { // 构造PDF的data URI const pdfDataUri = `data:application/pdf;base64,${base64Data}`; // 用InAppBrowser打开,_blank表示在新窗口打开 const browser = this.iab.create(pdfDataUri, '_blank', { location: 'yes', zoom: 'yes' }); browser.show(); }, error => { console.error('获取PDF失败:', error); }); }
这个方案的优势是简单快速,不需要操作本地文件;缺点是部分旧设备的WebView对大体积Base64的支持可能有限。
方案2:保存为本地文件后用Document Viewer打开
这是你提到的方案,给你补全具体实现代码:
- 安装所需插件:
# 文件操作插件 ionic cordova plugin add cordova-plugin-file npm install @ionic-native/file@4 # 文档查看器插件 ionic cordova plugin add cordova-plugin-document-viewer npm install @ionic-native/document-viewer@4
- 代码实现:
import { File } from '@ionic-native/file'; import { DocumentViewer } from '@ionic-native/document-viewer'; import { HttpClient } from '@angular/common/http'; constructor(private file: File, private documentViewer: DocumentViewer, private http: HttpClient) {} saveAndOpenPdf() { this.http.get('http://你的后端接口地址/generate-pdf-base64', { responseType: 'text' }).subscribe(base64Data => { // 将Base64转为Blob格式 const blob = this.base64ToBlob(base64Data, 'application/pdf'); // 定义文件名和存储路径(用应用私有目录,跨平台通用) const fileName = 'report.pdf'; const filePath = this.file.dataDirectory; // 写入本地文件 this.file.writeFile(filePath, fileName, blob, { replace: true }).then(() => { // 调用Document Viewer打开文件 const options = { title: '报表查看' }; this.documentViewer.viewDocument(`${filePath}${fileName}`, 'application/pdf', options); }).catch(error => { console.error('保存文件失败:', error); }); }, error => { console.error('获取PDF失败:', error); }); } // Base64转Blob的工具方法 private base64ToBlob(base64: string, contentType: string): Blob { const byteCharacters = atob(base64); const byteArrays = []; for (let offset = 0; offset < byteCharacters.length; offset += 512) { const slice = byteCharacters.slice(offset, offset + 512); const byteNumbers = new Array(slice.length); for (let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } return new Blob(byteArrays, { type: contentType }); }
这个方案兼容性更好,适合大文件,而且Document Viewer的体验更接近原生应用。
方案3:用PDF.js集成渲染(自定义查看器)
如果需要定制化的PDF查看体验(比如添加自定义工具栏、标注功能),可以集成PDF.js到Ionic 3中:
- 安装兼容Ionic 3的PDF.js版本:
npm install pdfjs-dist@2.0.943 --save
(注意要把node_modules/pdfjs-dist/build/pdf.worker.js复制到项目的assets目录下)
- 代码示例(在页面中渲染PDF):
import { HttpClient } from '@angular/common/http'; declare var pdfjsLib: any; constructor(private http: HttpClient) {} renderPdf() { this.http.get('http://你的后端接口地址/generate-pdf-base64', { responseType: 'text' }).subscribe(base64Data => { // 将Base64转为ArrayBuffer const pdfData = atob(base64Data); const arrayBuffer = new ArrayBuffer(pdfData.length); const uint8Array = new Uint8Array(arrayBuffer); for (let i = 0; i < pdfData.length; i++) { uint8Array[i] = pdfData.charCodeAt(i); } // 初始化PDF.js pdfjsLib.GlobalWorkerOptions.workerSrc = 'assets/pdf.worker.js'; pdfjsLib.getDocument(arrayBuffer).promise.then(pdf => { // 渲染第一页,如需分页可循环处理 pdf.getPage(1).then(page => { const canvas = document.getElementById('pdf-canvas') as HTMLCanvasElement; const ctx = canvas.getContext('2d'); const viewport = page.getViewport({ scale: 1.5 }); canvas.height = viewport.height; canvas.width = viewport.width; page.render({ canvasContext: ctx, viewport: viewport }); }); }); }, error => { console.error('获取PDF失败:', error); }); }
然后在页面模板中添加用于渲染的canvas:
<canvas id="pdf-canvas"></canvas>
这个方案适合需要深度定制的场景,但需要自己处理分页、缩放等细节功能。
总结
- 追求简单快速:选方案1;
- 看重原生体验和兼容性:选方案2;
- 需要自定义PDF查看功能:选方案3。
内容的提问来源于stack exchange,提问作者ezolton
相关产品推荐
相关产品推荐

