You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle APEX中用jsPDF合并3张图片为PDF的问题及存库需求

解决Oracle APEX中jsPDF合并图片缺失及PDF存入数据库问题

一、第三张图片无法加入PDF的问题修复

问题原因

  1. 异步读取逻辑不可靠:原代码依赖FileReader的onload回调判断文件读取完成,但异步操作的触发顺序不固定,可能导致PDF生成逻辑在第三张图片未完全加载时就执行。
  2. 页面删除逻辑错误:每添加一张图片就调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 15:47:10