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

在WordPress中用Blob和Ajax实现图片存储与展示的技术问题

基于WordPress的文档照片上传与存储问题

我正在开发一个WordPress网站,功能是让用户拍摄文档照片后上传到服务器存储,供教师等人员审核照片是否合规。我现在是把图片转换成Blob对象,再用Ajax发送到服务器,但作为Web开发新手,我不知道怎么把图片存储到WordPress数据库,也不清楚后续怎么把Blob还原成图片展示。以下是我目前写的代码:


HTML代码

<table>
    <tr>
        <td><video autoplay="true" id="video"></video></td>
        <td><canvas id="canvas"></canvas></td>
        <td><button id="btn"> Take Picture </button></td>
        <td><button id="sub"> Einreichen </button></td>
    </tr>
</table>

JavaScript代码(含WordPress钩子)

// 加载jQuery
wp_enqueue_script('jquery');

// 定义AJAX地址
function myplugin_ajaxurl() {
   echo '<script type="text/javascript">
           var ajaxurl = "' . admin_url('admin-ajax.php') . '";
         </script>';
}
add_action('wp_head', 'myplugin_ajaxurl');

// 前端脚本
function add_this_script_footer(){ ?>
    <script>
    const video = document.querySelector('#video')
    const btn = document.querySelector('#btn')
    const canvas = document.querySelector('#canvas')
    const submit = document.querySelector('#sub')
    const photo = document.querySelector('#photo')
    var capturedBlob;
    
    function capturePhoto() {
        canvas.width = 500;
        canvas.height = 600;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(video, 0, 0);
        canvas.toBlob(function(blob) {
            // 预览图片
            const img = document.createElement('img');
            img.src = URL.createObjectURL(blob);
            document.body.appendChild(img);
            capturedBlob = blob;
        }, "image/jpeg", 0.75);
    }

    if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
        navigator.mediaDevices.getUserMedia({video: true})
            .then(stream => {
                video.srcObject = stream
            })
            .catch(error => {
                console.log('访问摄像头时出错。')
            })
    }

    btn.addEventListener('click', capturePhoto);

    jQuery(document).ready(function($) {
        $("#sub").click(function() {
            if (!capturedBlob) {
                alert('请先拍摄照片!');
                return;
            }
            const formData = new FormData();
            formData.append('action', 'example_ajax_request');
            // 给Blob添加文件名,方便后端识别
            formData.append('file', capturedBlob, 'document_photo_' + Date.now() + '.jpg');
            
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: formData,
                processData: false,
                contentType: false,
                success:function(data) {
                    const response = JSON.parse(data);
                    if (response.success) {
                        alert('上传成功!图片ID:' + response.attachment_id);
                    } else {
                        alert('上传失败:' + response.error);
                    }
                },
                error: function(errorThrown){
                    alert('请求出错:' + errorThrown.responseText);
                }
            });
        });
    });
    </script>
<?php }
add_action('wp_footer', 'add_this_script_footer');

原PHP代码

// 处理AJAX请求的PHP
function example_ajax_request() {
    if ( isset($_POST) ) {
        $file = $_FILES['file'];
        echo $file;
        
        // 这里需要添加文件存储逻辑
        
        // 返回结果给前端
        //echo $file;
    }
    die();
}
add_action( 'wp_ajax_example_ajax_request', 'example_ajax_request' );
add_action( 'wp_ajax_nopriv_example_ajax_request', 'example_ajax_request' );

解决方案

一、修复前端Blob传递问题

原代码存在核心问题:传递Blob时未指定文件名,导致后端无法正确识别为文件。修正后的JS代码做了以下优化:

  • 变量名改为capturedBlob,语义更清晰
  • 传递FormData时为Blob指定唯一文件名:formData.append('file', capturedBlob, 'document_photo_' + Date.now() + '.jpg')
  • 添加未拍摄照片时的提示逻辑

二、后端将图片存储到WordPress媒体库(推荐方案)

WordPress媒体库自带文件管理、权限控制、缩略图生成等功能,比直接操作数据库更规范。修改PHP处理函数如下:

function example_ajax_request() {
    // 权限验证:仅允许登录用户上传(可根据需求调整)
    if (!is_user_logged_in()) {
        wp_send_json_error('请先登录!');
    }

    // 检查文件上传状态
    if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
        wp_send_json_error('文件上传失败,请重试!');
    }

    $file = $_FILES['file'];
    $upload_dir = wp_upload_dir();
    $file_path = $upload_dir['path'] . '/' . basename($file['name']);

    // 将临时文件移动到WordPress上传目录
    if (!move_uploaded_file($file['tmp_name'], $file_path)) {
        wp_send_json_error('无法保存文件到服务器!');
    }

    // 准备媒体库附件数据
    $attachment_data = array(
        'guid'           => $upload_dir['url'] . '/' . basename($file['name']),
        'post_mime_type' => $file['type'],
        'post_title'     => sanitize_file_name(basename($file['name'])),
        'post_content'   => '',
        'post_status'    => 'inherit'
    );

    // 将文件添加到媒体库
    $attachment_id = wp_insert_attachment($attachment_data, $file_path);

    // 生成附件元数据(缩略图、尺寸信息等)
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    $attachment_metadata = wp_generate_attachment_metadata($attachment_id, $file_path);
    wp_update_attachment_metadata($attachment_id, $attachment_metadata);

    // 返回成功信息与图片URL
    wp_send_json_success(array(
        'attachment_id' => $attachment_id,
        'image_url' => wp_get_attachment_url($attachment_id)
    ));

    die();
}
add_action( 'wp_ajax_example_ajax_request', 'example_ajax_request' );
add_action( 'wp_ajax_nopriv_example_ajax_request', 'example_ajax_request' );

三、还原并展示图片

存储到媒体库后,有两种常用展示方式:

  1. 通过附件ID获取URL:使用WordPress内置函数wp_get_attachment_url($attachment_id)获取图片完整URL,直接在前端用<img src="图片URL">展示。
  2. 自定义字段存储(不推荐):若需将图片内容存在自定义表,需先把Blob转为Base64字符串存储,展示时用<img src="data:image/jpeg;base64,Base64字符串">,但这种方式性能远不如媒体库。

四、额外优化建议

  • 权限控制:给审核页面添加角色验证,比如仅允许editor或自定义教师角色访问。
  • 合规检查:后端可添加图片尺寸、文件大小校验,甚至结合OCR识别文档内容。
  • 错误日志:在PHP中添加错误日志记录,方便排查上传失败问题。

内容的提问来源于stack exchange,提问作者Krupp J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:40:01