Cordova应用点击保存后在Safari打开PDF的实现求助
问题:Cordova App中PDF生成后无法保存,需在Safari中打开PDF
我有一段HTML代码,已通过Cordova转换为App。网页端点击保存按钮可将页面内容转为PDF并保存,但Cordova生成的App中点击保存仅打开页面无保存选项,需实现点击保存后在Safari中打开PDF。已尝试多种方法未解决,已安装cordova-pdf-generator和cordova-plugin-inappbrowser插件,恳请提供帮助,谢谢!
原始代码
function saveData() { const customerData = { customerName: document.getElementById('customerName').value, orderNumber: document.getElementById('orderNumber').value, storeNumber: document.getElementById('storeNumber').value, date: document.getElementById('date').value, // intallerID: document.getElementById('intallerID').value, // intallerName: document.getElementById('intallerName').value, }; const roomElement = document.getElementById(`room${windowSectionCounter}`); if (roomElement) { roomElement.value = roomElement.value.toUpperCase(); } const windowDataList = []; const windowSections = document.querySelectorAll('windowInfoSection'); windowSections.forEach((windowSection, index) => { // Add a check for null before accessing properties const roomElement = windowSection.querySelector('input[name="room"]'); const quantityElement = windowSection.querySelector('quantity'); const mountElement = windowSection.querySelector('mount'); const widthElement = windowSection.querySelector('width'); const heightElement = windowSection.querySelector('height'); const depthElement = windowSection.querySelector('depth'); if (roomElement && quantityElement && mountElement && widthElement && heightElement && depthElement) { const convertedWidth = convertDimensionsToFraction(parseFloat(widthElement.value)); const convertedHeight = convertDimensionsToFraction(parseFloat(heightElement.value)); const windowData = { room: roomElement.value, quantity: quantityElement.value, mount: mountElement.value, width: widthElement.value, height: heightElement.value, depth: depthElement.value, }; windowDataList.push(windowData); } else { console.error('One or more elements in the window section are null.'); } }); console.log('Customer Data:', customerData); console.log('Window Data List:', windowDataList); // Generate PDF const pdfData = { customerData, windowDataList, }; generatePDF(pdfData); } function generatePDF(data) { const addButton = document.getElementById('addWindowButton'); const saveButton = document.getElementById('saveButton'); const clearButton = document.getElementById('clearButton'); const commentButton = document.getElementById('commentButton'); const removeWindowButton = document.getElementById('removeWindowButton'); const removeCommentButton = document.getElementById('removeCommentButton'); addButton.style.display = 'none'; saveButton.style.display = 'none'; clearButton.style.display = 'none'; commentButton.style.display = 'none'; removeWindowButton.style.display = 'none'; removeCommentButton.style.display = 'none'; // Extract customer name and order number from the data const customerName = data.customerData.customerName; const orderNumber = data.customerData.orderNumber; // Convert spaces to underscores and remove any special characters const sanitizedCustomerName = customerName.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''); const sanitizedOrderNumber = orderNumber.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''); // Generate PDF with customer name and order number in the filename html2pdf().from(document.body) .set({ filename: `${sanitizedCustomerName}_${sanitizedOrderNumber}.pdf`, image: { type: 'jpeg', quality: 0.98 }, // html2canvas: { scale: 1.5 }, // Reduced scale jsPDF: { unit: 'mm', format: 'a3', orientation: 'landscape' }, }) .toPdf() .get('pdf') .then(function (pdf) { const totalPages = pdf.internal.getNumberOfPages(); pdf.setFontSize(10); // Set the font size for the page numbers pdf.setTextColor(150); // Set the text color for the page numbers for (let i = 1; i <= totalPages; i++) { pdf.setPage(i); pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth() - 30, pdf.internal.pageSize.getHeight() - 5); } }) .save() .then(() => { addButton.style.display = 'inline-block'; saveButton.style.display = 'inline-block'; clearButton.style.display = 'inline-block'; commentButton.style.display = 'inline-block'; removeWindowButton.style.display = 'inline-block'; removeCommentButton.style.display = 'inline-block'; }) .catch((error) => { console.error('Error generating PDF:', error); addButton.style.display = 'inline-block'; saveButton.style.display = 'inline-block'; clearButton.style.display = 'inline-block'; commentButton.style.display = 'inline-block'; removeWindowButton.style.display = 'inline-block'; removeCommentButton.style.display = 'inline-block'; }); }
解决方案
1. 修改PDF生成逻辑,改用InAppBrowser在Safari打开
原代码中html2pdf().save()在Cordova iOS环境下无法触发系统保存弹窗,需改为生成Blob数据后,调用cordova-plugin-inappbrowser以系统浏览器(Safari)打开PDF,此时Safari会提供保存、打印等选项。
修改后的generatePDF函数
function generatePDF(data) { const addButton = document.getElementById('addWindowButton'); const saveButton = document.getElementById('saveButton'); const clearButton = document.getElementById('clearButton'); const commentButton = document.getElementById('commentButton'); const removeWindowButton = document.getElementById('removeWindowButton'); const removeCommentButton = document.getElementById('removeCommentButton'); addButton.style.display = 'none'; saveButton.style.display = 'none'; clearButton.style.display = 'none'; commentButton.style.display = 'none'; removeWindowButton.style.display = 'none'; removeCommentButton.style.display = 'none'; const customerName = data.customerData.customerName; const orderNumber = data.customerData.orderNumber; const sanitizedCustomerName = customerName.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''); const sanitizedOrderNumber = orderNumber.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''); const fileName = `${sanitizedCustomerName}_${sanitizedOrderNumber}.pdf`; html2pdf().from(document.body) .set({ image: { type: 'jpeg', quality: 0.98 }, jsPDF: { unit: 'mm', format: 'a3', orientation: 'landscape' }, }) .toPdf() .get('pdf') .then(function (pdf) { // 添加页码逻辑不变 const totalPages = pdf.internal.getNumberOfPages(); pdf.setFontSize(10); pdf.setTextColor(150); for (let i = 1; i <= totalPages; i++) { pdf.setPage(i); pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth() - 30, pdf.internal.pageSize.getHeight() - 5); } // 生成PDF的Blob数据 return pdf.output('blob'); }) .then(function(blob) { // 创建Blob本地URL const blobUrl = URL.createObjectURL(blob); // 调用InAppBrowser以系统浏览器(Safari)打开PDF cordova.InAppBrowser.open(blobUrl, '_system', 'location=yes'); // 延迟释放URL,避免打开前被回收 setTimeout(() => URL.revokeObjectURL(blobUrl), 10000); }) .then(() => { // 恢复按钮显示 addButton.style.display = 'inline-block'; saveButton.style.display = 'inline-block'; clearButton.style.display = 'inline-block'; commentButton.style.display = 'inline-block'; removeWindowButton.style.display = 'inline-block'; removeCommentButton.style.display = 'inline-block'; }) .catch((error) => { console.error('Error generating PDF:', error); // 出错后也恢复按钮显示 addButton.style.display = 'inline-block'; saveButton.style.display = 'inline-block'; clearButton.style.display = 'inline-block'; commentButton.style.display = 'inline-block'; removeWindowButton.style.display = 'inline-block'; removeCommentButton.style.display = 'inline-block'; }); }
2. 确认插件配置
检查config.xml是否已正确添加cordova-plugin-inappbrowser:
<plugin name="cordova-plugin-inappbrowser" spec="^5.0.0" />
3. 确保Cordova初始化完成
所有依赖Cordova插件的代码必须在deviceready事件触发后执行,比如按钮点击事件绑定:
document.addEventListener("deviceready", function() { // 绑定保存按钮点击事件 document.getElementById('saveButton').addEventListener('click', saveData); }, false);
内容的提问来源于stack exchange,提问作者user1742718
相关产品推荐
相关产品推荐

