Oracle APEX中用jsPDF合并3张图片为PDF的问题及存库需求
解决Oracle APEX中jsPDF合并图片缺失及PDF存入数据库问题
一、第三张图片无法加入PDF的问题修复
问题原因
- 异步读取逻辑不可靠:原代码依赖
FileReader的onload回调判断文件读取完成,但异步操作的触发顺序不固定,可能导致PDF生成逻辑在第三张图片未完全加载时就执行。 - 页面删除逻辑错误:每添加一张图片就调用
addPage(),三张图片会生成4页PDF(初始1页+3次新增页面),但原代码删除的是第3页(selectedFiles.length=3),恰好删掉了第三张图片所在的页面。
修复代码
改用Promise统一处理所有文件的异步读取,确保所有图片加载完成后再生成PDF,同时修正页面添加逻辑(最后一张图片不新增空白页):
// Function to handle file uploads and PDF creation function handleFileUpload() { var itemNames = ['P29_NEW', 'P29_NEW_1', 'P29_NEW_1_1']; var filePromises = []; var imgToPdf = new jsPDF(); // 遍历文件输入,封装为Promise处理异步读取 itemNames.forEach(function(itemName) { var fileInput = $x(itemName); if (!fileInput.files || !fileInput.files[0]) { alert('请选择所有文件。'); throw new Error('缺少文件'); } var file = fileInput.files[0]; // 文件大小验证 if (file.size > 5 * 1024 * 1024) { alert('文件大小超过5MB限制。'); throw new Error('文件过大'); } // 文件类型验证 var fileType = getFileExtension(file.name); if (fileType !== 'JPEG' && fileType !== 'JPG' && fileType !== 'PNG') { alert('请上传JPEG、JPG或PNG格式的图片。'); throw new Error('文件格式错误'); } // 封装读取操作为Promise var readPromise = new Promise(function(resolve) { var reader = new FileReader(); reader.onload = function(e) { resolve({ name: file.name, data: e.target.result, type: fileType }); }; reader.readAsDataURL(file); }); filePromises.push(readPromise); }); // 等待所有文件读取完成后生成PDF Promise.all(filePromises) .then(function(selectedFiles) { selectedFiles.forEach(function(file, index) { imgToPdf.addImage(file.data, file.type, 20, 10, 150, 200); // 最后一张图片不添加空白页 if (index !== selectedFiles.length - 1) { imgToPdf.addPage(); } }); // 保存PDF为Blob var pdfContent = imgToPdf.output('blob'); // 浏览器下载PDF imgToPdf.save('merged_images.pdf'); // 将PDF存入数据库 savePdfToDB(pdfContent); }) .catch(function(err) { console.error(err); }); } // Function to get file extension function getFileExtension(filename) { return filename.split('.').pop().toUpperCase(); } // 调用函数 handleFileUpload();
二、通过apex.server.process将PDF存入Oracle数据库
步骤1:创建APEX AJAX进程
在Oracle APEX应用中创建AJAX Callback类型的进程,命名为SAVE_PDF_TO_DB,PL/SQL代码示例如下(假设存储表为PDF_STORAGE,包含ID NUMBER和PDF_DATA BLOB字段):
DECLARE l_blob BLOB; BEGIN -- 读取AJAX请求中的Blob数据 l_blob := apex_web_service.parse_blob(p_body => apex_application.g_request_body); -- 插入到数据库表(可根据需求添加主键、时间戳等字段) INSERT INTO PDF_STORAGE (PDF_DATA) VALUES (l_blob); COMMIT; END;
步骤2:JavaScript发送PDF到服务器
添加savePdfToDB函数,将Blob数据传递给上述AJAX进程:
function savePdfToDB(pdfBlob) { apex.server.process( 'SAVE_PDF_TO_DB', // 对应创建的AJAX进程名称 {}, { dataType: 'text', processData: false, contentType: false, rawBody: pdfBlob, // 直接传递Blob作为请求体 success: function(response) { alert('PDF已成功保存到数据库'); console.log('保存成功:', response); }, error: function(xhr, status, error) { alert('保存PDF到数据库失败'); console.error('保存失败:', error); } } ); }
注意事项
- 确保数据库表的
PDF_DATA字段类型为BLOB,且分配足够存储空间。 - 确保AJAX进程拥有目标表的插入权限。
- 若需传递额外业务参数(如用户ID、记录ID),可在
apex.server.process的第二个参数中添加,PL/SQL中通过apex_application.g_x01、apex_application.g_x02等变量获取。
内容的提问来源于stack exchange,提问作者Shivdutt
相关产品推荐
相关产品推荐

