问题背景
在使用Typecho后台编辑器(Markdown编辑器)写文章时,从剪贴板粘贴图片(例如截图、复制网页图片等),默认会保存为PNG格式。这会导致:
- 文件体积大:PNG是无损压缩,比JPG大很多
- 加载速度慢:大图片影响页面加载性能
- 存储浪费:占用宝贵的服务器空间
解决方案
通过修改 /admin/editor-js.php 文件中的剪贴板图片处理逻辑,实现了:
- PNG图片粘贴时自动转换为JPG格式
- 透明区域自动填充白色背景
- 压缩质量设置为90%,保持较好画质
- 文件后缀自动从
.png改为.jpg
代码修改
修改文件:/admin/editor-js.php
/**
* 剪贴板图片粘贴处理
*
* 功能说明:
* - 监听编辑器的粘贴事件,处理从剪贴板粘贴的图片
* - PNG图片自动转换为JPG格式,节省存储空间
* - PNG透明区域自动填充白色背景
* - 压缩质量设置为90%,保持较好画质
*
* 技术实现:
* 1. 使用 pastableTextarea 插件捕获 pasteImage 事件
* 2. 通过 Canvas API 将 PNG 转换为 JPG
* 3. fillRect 填充白色背景,因为 JPG 不支持透明
* 4. toBlob 生成新的 JPG Blob 对象
* 5. 修改文件后缀为 .jpg
*/
textarea.pastableTextarea().on("pasteImage", function (e, data) {
var name = data.name ? data.name.replace(/[()[]*#!]/g, "") : (new Date()).toISOString().replace(/..+$/, "");
// 检测是否为PNG格式图片
if (data.blob.type === "image/png") {
var canvas = document.createElement("canvas");
var img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
// 填充白色背景(PNG支持透明,JPG不支持)
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
// 转换为JPG格式,压缩质量90%
canvas.toBlob(function(jpgBlob) {
var jpgName = name.replace(/.png$/i, ".jpg");
if (!jpgName.match(/.jpg$/i)) {
jpgName += ".jpg";
}
Typecho.uploadFile(new File([jpgBlob], jpgName), jpgName);
}, "image/jpeg", 0.9);
};
img.src = URL.createObjectURL(data.blob);
} else {
// 非PNG图片保持原格式
if (!name.match(/.[a-z0-9]{2,}$/i)) {
var ext = data.blob.type.split("/").pop();
name += "." + ext;
}
Typecho.uploadFile(new File([data.blob], name), name);
}
});实现原理
- 事件监听:使用
pastableTextarea插件监听pasteImage事件 - 格式检测:通过
data.blob.type判断是否为image/png Canvas转换:
- 创建与原图相同尺寸的Canvas
- 填充白色背景(处理透明区域)
- 绘制原图
- 格式转换:使用
canvas.toBlob()生成JPG格式 - 上传文件:调用
Typecho.uploadFile()上传转换后的文件
效果对比
| 格式 | 典型截图大小 | 透明支持 |
|---|---|---|
| PNG | 200KB-500KB | 是 |
| JPG | 50KB-150KB | 否(填充白色) |
压缩率约 70-80%
适用场景
- 截图粘贴
- 网页图片复制
- 其他PNG格式图片
GIF、WebP等非PNG格式保持原样上传,不受影响。
本文档记录于 2026-04-08
暂无评论