UEditor 图片转存完整教程

什么是图片转存?为什么需要它?

图片转存,也叫“图片上传”或“图片抓取”,指的是当你在 UEditor 编辑器中从其他网站复制图片并粘贴(Ctrl+V)时,UEditor 会自动将这些外部图片下载到你自己的服务器上,然后用你服务器上的图片地址替换掉原来的外部链接。

ueditor 图片转存 教程
(图片来源网络,侵删)

为什么需要它?

  1. 防盗链与失效:直接引用外部图片,如果原网站删除了图片、修改了路径或开启了防盗链,你网站上的图片就会失效(显示为叉号或空白)。
  2. 加载速度:用户访问你的网站时,如果图片资源来自其他域名,会增加额外的 HTTP 请求,影响页面加载速度。
  3. 数据安全与可控性:将图片存储在自己的服务器上,保证了内容的永久性和可控性,避免了依赖第三方服务的风险。

工作原理

图片转存的核心流程如下:

  1. 用户粘贴:用户在 UEditor 编辑器中从外部网页复制图片,然后点击“粘贴”按钮或直接使用 Ctrl+V
  2. 前端捕获:UEditor 前端会捕获到这个操作,并利用正则表达式从 HTML 内容中提取出所有 <img> 标签的 src 属性值(即外部图片的 URL)。
  3. 异步上传:UEditor 将这些提取出的 URL 列表,通过一个 AJAX 请求发送到你指定的后端接口(config.json 中配置的 imageManagerActionName)。
  4. 后端处理
    • 后端接收到这些 URL 列表。
    • 遍历每个 URL,使用服务器端代码(如 PHP 的 file_get_contents,Node.js 的 axios,Java 的 HttpClient 等)下载图片内容。
    • 为下载的图片生成一个唯一的、符合你规则的文件名(例如使用时间戳+随机数)。
    • 保存到你服务器的指定目录(/upload/image/)。
    • 记录下新图片的 URL(http://your-domain.com/upload/image/1623456789_a.jpg)。
  5. 返回结果:后端将一个 JSON 对象返回给前端,这个对象包含了“旧 URL”到“新 URL”的映射关系。
  6. 前端替换:UEditor 前端接收到这个 JSON 对象后,根据映射关系,将编辑器内容中的旧图片 URL 替换为新的、指向你服务器的 URL。
  7. 最终保存:用户完成编辑后,点击“发布”或“保存”,编辑器中就只包含你服务器上的图片了。

前端配置

配置主要在 UEditor 初始化时传入的 config 对象中进行。

关键配置项:

ueditor 图片转存 教程
(图片来源网络,侵删)
  1. enableUploadImage:是否允许上传图片,默认为 true,确保开启。
  2. imageActionName:这个配置用于“本地上传”功能,可以忽略或保持默认。
  3. imageManagerActionName这是图片转存的核心配置项,它指定了处理图片转存请求的后端接口名称,默认值是 getRemoteImage
  4. imageMaxSize:允许上传图片的最大尺寸,单位 KB,可以根据需要调整。
  5. imageAllowFiles:允许上传的图片文件类型,如 ["png", "jpg", "jpeg"]

示例代码:

<!DOCTYPE html>
<html>
<head>UEditor 示例</title>
    <!-- 引入 UEditor 核心文件 -->
    <script type="text/javascript" charset="utf-8" src="ueditor.config.js"></script>
    <script type="text/javascript" charset="utf-8" src="ueditor.all.min.js"></script>
    <!-- 引入语言文件,默认是 zh-cn -->
    <script type="text/javascript" charset="utf-8" src="lang/zh-cn/zh-cn.js"></script>
</head>
<body>
    <h1>UEditor 图片转存示例</h1>
    <div id="editor" style="width: 1024px; height: 500px;"></div>
    <script type="text/javascript">
        // 初始化 UEditor
        var ue = UE.getEditor('editor', {
            // 这里是配置项
            initialFrameWidth: 1024,
            initialFrameHeight: 500,
            // 图片转存相关配置
            enableUploadImage: true, // 开启图片上传功能
            imageManagerActionName: 'getRemoteImage', // 图片转存的后端接口名,默认就是这个
            imageMaxSize: 2048, // 2MB
            imageAllowFiles: [
                '.png', '.jpg', '.jpeg', '.gif', '.bmp'
            ]
        });
    </script>
</body>
</html>

后端实现(以 PHP 为例)

这是整个流程中最关键的一步,你需要创建一个后端脚本来处理 getRemoteImage 这个请求。

假设你的 Uditor 根目录在 /ueditor/,那么你需要创建一个文件:/ueditor/php/getRemoteImage.php

getRemoteImage.php 完整代码:

ueditor 图片转存 教程
(图片来源网络,侵删)
<?php
/**
 * 图片远程转存
 */
/*
 * 程序配置项
 */
$config = array(
    'savePath' => dirname(__FILE__) . '/../../../../upload/image/', // 保存路径,建议以 "/" 
    'allowFiles' => array( // 允许的文件后缀
        '.png', '.jpg', '.jpeg', '.gif', '.bmp'
    ),
    'maxSize' => 3000, // 文件大小限制,单位KB
);
// 检查目录是否存在,不存在则创建
if (!file_exists($config['savePath'])) {
    mkdir($config['savePath'], 0777, true);
}
// 获取配置
$savePath = $config['savePath'];
$allowFiles = $config['allowFiles'];
$maxSize = $config['maxSize'] * 1024; // 转换为字节
// 获取到源列表
$source = $_POST['source'];
// 返回结果
$result = array();
foreach ($source as $img) {
    // 获取图片信息
    $imgInfo = getimagesize($img);
    if (!$imgInfo) {
        continue; // 如果不是图片,跳过
    }
    // 检查文件大小 (通过 Content-Length)
    $headers = get_headers($img, 1);
    if (isset($headers['Content-Length']) && $headers['Content-Length'] > $maxSize) {
        continue; // 如果文件过大,跳过
    }
    // 获取文件后缀
    $fileType = '';
    if (isset($imgInfo['mime'])) {
        $mimeToExt = [
            'image/jpeg' => '.jpg',
            'image/png' => '.png',
            'image/gif' => '.gif',
            'image/bmp' => '.bmp',
            'image/webp' => '.webp'
        ];
        $fileType = isset($mimeToExt[$imgInfo['mime']]) ? $mimeToExt[$imgInfo['mime']] : '';
    }
    if (!in_array($fileType, $allowFiles)) {
        continue; // 如果后缀不被允许,跳过
    }
    // 生成唯一文件名
    $fileName = time() . mt_rand(1000, 9999) . $fileType;
    $filePath = $savePath . $fileName;
    // 下载并保存图片
    if (file_put_contents($filePath, file_get_contents($img))) {
        // 构建完整的URL,请根据你的域名和路径修改
        $localUrl = 'http://your-domain.com/upload/image/' . $fileName;
        $result[] = array(
            'state' => 'SUCCESS',
            'url' => $localUrl,
            'source' => $img,
            'title' => $fileName
        );
    }
}
// 输出结果
echo json_encode(array(
    'state' => count($result) > 0 ? 'SUCCESS' : 'ERROR_NO_SOURCE',
    'list' => $result
));
/**
 * 获取文件后缀
 */
function getExt($url)
{
    $path = parse_url($url);
    $path = pathinfo($path['path']);
    return isset($path['extension']) ? '.' . $path['extension'] : '';
}

代码关键点解释:

  1. savePath请务必修改为你自己的服务器上用于存储图片的绝对路径或相对于当前脚本的路径,注意路径末尾最好加上 。
  2. allowFiles:和前端的配置保持一致,只允许指定的图片类型。
  3. $_POST['source']:这是前端传过来的图片 URL 数组。
  4. 循环处理:遍历每一个 URL。
  5. 安全检查getimagesize()get_headers() 用来验证 URL 是否真的是一个图片,并检查其大小,防止恶意上传。
  6. 生成文件名:使用 time()mt_rand() 组合生成一个几乎唯一的文件名,避免文件名冲突。
  7. file_put_contents($filePath, file_get_contents($img)):这是核心下载和保存操作。file_get_contents() 从远程 URL 读取内容,file_put_contents() 将内容写入本地文件。
  8. 构建返回 URL$localUrl 是最关键的一步,这里必须填写图片在你的网站上的完整可访问 URLhttp://www.yourdomain.com/path/to/image.jpg,前端会用这个 URL 来替换图片。
  9. json_encode($result):将处理结果以 JSON 格式返回给前端。

常见问题与解决方案 (FAQ)

Q1: 粘贴图片后没反应,或者图片叉了。

  • 原因:通常是后端接口未正确配置或路径错误。
  • 排查
    1. 打开浏览器的开发者工具(F12),切换到 "Network"(网络)标签。
    2. 尝试粘贴一张图片,看看有没有一个名为 getRemoteImage 的请求发出。
    3. 检查这个请求的 Status(状态码)和 Response)。
    4. 如果状态码是 404 或 500,说明后端脚本有问题,请检查 getRemoteImage.php 文件是否存在,以及 imageManagerActionName 配置是否正确。
    5. 如果状态码是 200,但 Response 内容是 {"state":"ERROR_NO_SOURCE","list":[]},说明后端没有成功处理任何图片,请检查 getRemoteImage.php 中的 savePath 是否正确,是否有写入权限,以及 $localUrl 是否构建正确。

Q2: 图片上传成功,但前台无法显示。

  • 原因:99% 的情况是 $localUrl 构建错误,你返回给前端的 URL 必须是一个可以通过 HTTP 访问到的有效地址
  • 解决方案:在 getRemoteImage.php 中,将 $localUrl 修改为正确的公网 URL,如果你的网站是 http://example.com,图片保存在 /var/www/html/uploads/ 目录下,$localUrl 就应该是 http://example.com/uploads/ + $fileName

Q3: 如何处理跨域问题?

  • 原因:如果图片源站(img.example.com)没有允许你的域名跨域,那么浏览器会因为安全策略(CORS)而阻止 file_get_contents() 或 AJAX 请求获取图片数据。
  • 解决方案
    1. 最佳方案:让图片源站的运维人员配置 CORS,在你的域名下添加 Access-Control-Allow-Origin 响应头。
    2. 备用方案:如果无法控制源站,可以在后端使用支持代理的 HTTP 客户端(如 PHP 的 cURL 设置 CURLOPT_FOLLOWLOCATION)或者通过一个中间代理服务器来下载图片,但这会增加复杂性和延迟。

Q4: 安全性如何保证?

  • 风险:直接接受用户提交的 URL 可能被用于恶意攻击,比如上传非法内容或造成服务器负载过高。
  • 建议
    1. 白名单:如果条件允许,只允许从特定域名(如你自己的其他域名)抓取图片。
    2. 内容校验:在后端对下载的图片内容进行二次校验,例如使用 exif_imagetype() 等函数确保它确实是图片文件,防止伪装成图片的脚本文件上传。
    3. 文件名处理:对文件名进行过滤,避免特殊字符导致路径错误或安全问题。
    4. 速率限制:对单个用户的转存请求频率进行限制,防止滥用。

通过以上步骤,你应该就能成功配置并使用 UEditor 的图片转存功能了,核心在于前端正确配置接口名后端正确处理请求并返回可访问的 URL