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

求助:实现Summernote提交时上传图片而非即时上传

我明白你的痛点——用户中途放弃操作却留下一堆冗余的服务器图片确实很头疼。咱们可以通过拦截Summernote的默认图片上传行为,先把图片转为本地预览(Base64格式),等用户点击提交按钮时再批量上传图片并替换编辑器内容里的临时地址,最后提交完整数据。下面是具体实现步骤:

1. 修改Summernote初始化配置,拦截自动上传

首先要禁用Summernote默认的图片自动上传逻辑,转而将图片转为Base64显示在编辑器中,同时把图片文件暂存到全局数组里:

// 全局数组存储待上传的图片文件,用于后续批量提交
let pendingImages = [];

$('#summernote').summernote({
  placeholder: 'your Message',
  height: 200,
  toolbar: [
    ['style', ['style']],
    ['font', ['bold', 'italic', 'underline', 'clear']],
    ['fontname', ['fontname']],
    ['insert', ['picture']], // 保留图片插入按钮
    // 其他工具栏选项按需添加
  ],
  callbacks: {
    // 拦截图片上传的默认行为
    onImageUpload: function(files) {
      // 阻止Summernote自动发起上传请求
      event.preventDefault();
      
      // 遍历用户选中的所有图片
      Array.from(files).forEach(file => {
        // 使用FileReader将图片转为Base64,实现本地预览
        const reader = new FileReader();
        reader.onload = function(e) {
          // 将Base64图片插入编辑器
          $('#summernote').summernote('insertImage', e.target.result, file.name);
        };
        reader.readAsDataURL(file);
        
        // 将图片文件存入待上传数组
        pendingImages.push(file);
      });
    },
    // 可选优化:监听编辑器内容变化,清理已删除的待上传图片
    onChange: function(contents) {
      pendingImages = pendingImages.filter(file => {
        const base64Prefix = `data:${file.type};base64,`;
        // 检查当前编辑器内容中是否还存在该图片的Base64标识
        return contents.includes(base64Prefix);
      });
    }
  }
});

2. 处理表单提交逻辑:先传图片,再提交数据

监听表单的提交事件,先批量上传所有暂存的图片,拿到服务器返回的真实URL后,替换编辑器里的Base64地址,最后再提交完整表单数据:

// 假设你的表单ID为#submit-form
$('#submit-form').on('submit', function(e) {
  // 先阻止表单默认提交行为
  e.preventDefault();
  const form = this;

  // 如果有待上传的图片,先执行图片上传流程
  if (pendingImages.length > 0) {
    const formData = new FormData();
    // 将所有待上传图片添加到FormData
    pendingImages.forEach((file, index) => {
      formData.append(`images[${index}]`, file);
    });

    // 发送图片上传请求(替换为你的后端上传接口地址)
    $.ajax({
      url: '/your-image-upload-api',
      method: 'POST',
      data: formData,
      processData: false, // 必须设置,避免jQuery自动处理FormData
      contentType: false, // 必须设置,让浏览器自动生成正确的Content-Type
      success: function(response) {
        // 假设后端返回格式为 { imageUrls: ['/uploads/img1.jpg', '/uploads/img2.jpg'] }
        const imageUrls = response.imageUrls;
        
        // 获取当前编辑器内容
        let content = $('#summernote').summernote('code');
        
        // 将编辑器中的Base64图片地址替换为服务器真实URL
        pendingImages.forEach((file, index) => {
          const base64Prefix = `data:${file.type};base64,`;
          // 正则匹配并替换对应的Base64地址
          content = content.replace(new RegExp(base64Prefix + '.*?"', 'g'), `${imageUrls[index]}"`);
        });
        
        // 更新编辑器内容为替换后的真实URL
        $('#summernote').summernote('code', content);
        
        // 清空待上传图片数组
        pendingImages = [];
        
        // 图片处理完成,正式提交表单
        form.submit();
      },
      error: function(err) {
        console.error('图片上传失败:', err);
        alert('图片上传失败,请重试');
      }
    });
  } else {
    // 没有待上传图片,直接提交表单
    form.submit();
  }
});

3. 后端接口参考逻辑(以PHP为例)

后端需要接收批量图片,处理后返回对应的URL数组,示例代码如下:

<?php
$imageUrls = [];
$uploadDir = 'uploads/';

// 确保上传目录存在且有写入权限
if (!is_dir($uploadDir)) {
  mkdir($uploadDir, 0755, true);
}

if (isset($_FILES['images'])) {
  foreach ($_FILES['images']['tmp_name'] as $key => $tmpName) {
    // 生成唯一文件名,避免重名
    $ext = pathinfo($_FILES['images']['name'][$key], PATHINFO_EXTENSION);
    $fileName = uniqid() . '.' . $ext;
    $uploadPath = $uploadDir . $fileName;
    
    // 移动临时文件到上传目录
    if (move_uploaded_file($tmpName, $uploadPath)) {
      // 生成可访问的URL(根据你的服务器配置调整)
      $imageUrls[] = '/' . $uploadPath;
    }
  }
}

// 返回JSON格式的URL数组
header('Content-Type: application/json');
echo json_encode(['imageUrls' => $imageUrls]);
?>

这样就能实现“仅在点击提交时上传图片”的需求,用户中途放弃操作时,未提交的图片只会留在本地,不会占用服务器存储空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:19:45