图床v0.1
功能概述
图床上传器新增了“截图后直接粘贴上传”功能。

用户在电脑上截图后,只需要回到图床上传器页面,按下:
- Windows / Linux:
Ctrl + V - macOS:
Cmd + V
页面会自动读取剪贴板中的图片,并调用原有上传逻辑完成上传。
上传成功后,仍然沿用原来的行为:
- 自动显示上传结果
- 自动复制图片链接
- 支持手动点击“复制链接”
- 继续使用原有
secret_token - 继续使用原有
/upload_file上传接口
修改文件
/var/www/img-uploader/index.html
新增功能点
1. 支持剪贴板图片上传
新增了全局 paste 事件监听:
document.addEventListener('paste', e => {
const clipboardData = e.clipboardData;
if (!clipboardData) return;
const items = Array.from(clipboardData.items || []);
const filesFromItems = items
.filter(item => item.type && item.type.startsWith('image/'))
.map((item, index) => {
const blob = item.getAsFile();
if (!blob) return null;
return createPastedImageFile(blob, index);
})
.filter(Boolean);
const filesFromClipboard = Array.from(clipboardData.files || [])
.filter(file => file.type && file.type.startsWith('image/'))
.map((file, index) => createPastedImageFile(file, index));
const pastedFiles = filesFromItems.length > 0 ? filesFromItems : filesFromClipboard;
if (pastedFiles.length === 0) return;
e.preventDefault();
dropzone.classList.add('pastehint');
setTimeout(() => {
dropzone.classList.remove('pastehint');
}, 500);
handleFiles(pastedFiles);
});
该逻辑会从剪贴板中提取图片文件,并交给原有的 handleFiles() 函数处理。
2. 新增粘贴图片文件生成函数
新增函数 createPastedImageFile(),用于把剪贴板中的图片数据转换成可上传的 File 对象。
function createPastedImageFile(blob, index) {
let ext = 'png';
if (blob.type === 'image/jpeg') ext = 'jpg';
else if (blob.type === 'image/webp') ext = 'webp';
else if (blob.type === 'image/gif') ext = 'gif';
else if (blob.type === 'image/bmp') ext = 'bmp';
return new File(
[blob],
`paste-${Date.now()}-${index}.${ext}`,
{
type: blob.type || 'image/png',
lastModified: Date.now()
}
);
}
生成的文件名格式为:
paste-时间戳-序号.扩展名
例如:
paste-1700000000000-0.png
3. 上传区增加粘贴提示
上传区提示文字从:
<p>把图片拖到这里,或者点击选择文件</p>
修改为:
<p>把图片拖到这里,点击选择文件,或截图后直接 Ctrl+V / Cmd+V 粘贴</p>
辅助说明文字更新为:
<div class="muted" style="margin-top:12px;">
支持多图上传,上传成功后会自动复制链接。截图后回到这个页面,直接按 Ctrl+V / Cmd+V 即可上传。
</div>
4. 粘贴上传时增加视觉反馈
新增 CSS 样式:
.dropzone.pastehint {
background: #064e3b;
border-color: #34d399;
}
当用户粘贴图片时,上传区域会短暂变色,提示已经识别到粘贴操作。
5. 优化文件选择逻辑
文件选择上传后,清空 fileInput.value:
fileInput.addEventListener('change', () => {
handleFiles(fileInput.files);
fileInput.value = '';
});
这样用户可以连续选择同一个文件进行上传测试。
6. 优化上传结果渲染方式
上传成功和失败结果改为通过 DOM 创建元素,而不是直接拼接 innerHTML。
这样可以减少 HTML 注入风险,也让“复制链接”按钮的事件绑定更稳定。
上传成功渲染函数:
function renderSuccess(item, fileName, url) {
item.textContent = '';
const title = document.createElement('strong');
title.className = 'success';
title.textContent = `上传成功:${fileName}`;
const box = document.createElement('div');
box.className = 'result';
const link = document.createElement('a');
link.href = url;
link.target = '_blank';
link.rel = 'noopener noreferrer';
link.textContent = url;
const br1 = document.createElement('br');
const br2 = document.createElement('br');
const copyBtn = document.createElement('button');
copyBtn.textContent = '复制链接';
copyBtn.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(url);
copyBtn.textContent = '已复制';
setTimeout(() => {
copyBtn.textContent = '复制链接';
}, 1200);
} catch (e) {
alert('复制失败,请手动复制链接');
}
});
box.appendChild(link);
box.appendChild(br1);
box.appendChild(br2);
box.appendChild(copyBtn);
item.appendChild(title);
item.appendChild(box);
}
上传失败渲染函数:
function renderError(item, fileName, message) {
item.textContent = '';
const title = document.createElement('strong');
title.className = 'error';
title.textContent = `上传失败:${fileName}`;
const box = document.createElement('div');
box.className = 'result';
box.textContent = message;
item.appendChild(title);
item.appendChild(box);
}
使用方式
- 打开图床上传器页面。
- 确认已经保存
secret_token。 - 使用系统截图工具截图。
- 回到上传器页面。
- 按下
Ctrl + V或Cmd + V。 - 图片会自动上传。
- 上传成功后,图片链接会自动复制到剪贴板。
支持的图片类型
当前会根据 MIME 类型识别以下格式:
| MIME 类型 | 文件扩展名 |
|---|---|
image/png |
.png |
image/jpeg |
.jpg |
image/webp |
.webp |
image/gif |
.gif |
image/bmp |
.bmp |
默认兜底格式为 .png。
验证方式
修改完成后刷新页面:
Ctrl + F5
然后进行测试:
- 截图一张图片。
- 打开上传器页面。
- 按
Ctrl + V。 - 上传区域短暂变色。
- 上传结果区域显示上传成功。
- 图片链接自动复制到剪贴板。
当前效果
图床上传器现在支持三种上传方式:
- 点击选择图片上传
- 拖拽图片到上传区域上传
- 截图后直接粘贴上传
新增粘贴上传功能没有修改后端接口,仍然复用原有 /upload_file 接口和 secret_token 鉴权逻辑。