```
feat(api): 添加Base64图片处理功能 - 在后端API中添加Base64图片处理逻辑,自动去除data URL头部信息 - 处理前端传来的包含header的Base64图片数据 refactor(video.js): 优化图片上传处理流程 - 将图片上传逻辑改为纯前端Base64处理,移除对后端上传接口的依赖 - 实现图片压缩功能,限制最大尺寸为2048像素 - 支持PNG和JPEG格式的图片压缩处理 - 移除原有的文件上传FormData方式,改用直接处理Base64数据 ```
This commit is contained in:
parent
85fb484bfa
commit
6cb6f9fc65
@ -130,6 +130,13 @@ def video_generate():
|
|||||||
"aspect_ratio": data.get('aspect_ratio', '9:16')
|
"aspect_ratio": data.get('aspect_ratio', '9:16')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 处理 Base64 图片 (去掉 header)
|
||||||
|
if payload.get("images"):
|
||||||
|
payload["images"] = [
|
||||||
|
img.split(',', 1)[1] if ',' in img else img
|
||||||
|
for img in payload["images"]
|
||||||
|
]
|
||||||
|
|
||||||
# 4. 启动异步视频任务
|
# 4. 启动异步视频任务
|
||||||
app = current_app._get_current_object()
|
app = current_app._get_current_object()
|
||||||
task_id = start_async_video_task(app, user_id, payload, cost, model_value)
|
task_id = start_async_video_task(app, user_id, payload, cost, model_value)
|
||||||
|
|||||||
@ -149,32 +149,72 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
showToast('已应用提示词模板', 'success');
|
showToast('已应用提示词模板', 'success');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 上传图片逻辑
|
// 图片处理辅助函数
|
||||||
|
const processImageFile = (file) => new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.onload = () => {
|
||||||
|
const maxDim = 2048;
|
||||||
|
let w = img.width;
|
||||||
|
let h = img.height;
|
||||||
|
|
||||||
|
if (w <= maxDim && h <= maxDim) {
|
||||||
|
resolve(e.target.result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w > h) {
|
||||||
|
if (w > maxDim) {
|
||||||
|
h = Math.round(h * (maxDim / w));
|
||||||
|
w = maxDim;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (h > maxDim) {
|
||||||
|
w = Math.round(w * (maxDim / h));
|
||||||
|
h = maxDim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = w;
|
||||||
|
canvas.height = h;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
ctx.drawImage(img, 0, 0, w, h);
|
||||||
|
// 保持原格式,如果不是 png 则默认 jpeg (0.9 质量)
|
||||||
|
const outType = file.type === 'image/png' ? 'image/png' : 'image/jpeg';
|
||||||
|
resolve(canvas.toDataURL(outType, 0.9));
|
||||||
|
};
|
||||||
|
img.onerror = reject;
|
||||||
|
img.src = e.target.result;
|
||||||
|
};
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 上传图片逻辑 (改为纯前端 Base64 处理)
|
||||||
fileInput.onchange = async (e) => {
|
fileInput.onchange = async (e) => {
|
||||||
const files = e.target.files;
|
const files = e.target.files;
|
||||||
if (files.length === 0) return;
|
if (files.length === 0) return;
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('images', files[0]);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
const r = await fetch('/api/upload', { method: 'POST', body: formData });
|
// 压缩并转换为 Base64
|
||||||
const d = await r.json();
|
uploadedImageUrl = await processImageFile(files[0]);
|
||||||
if (d.urls && d.urls.length > 0) {
|
|
||||||
uploadedImageUrl = d.urls[0];
|
imagePreview.innerHTML = `
|
||||||
imagePreview.innerHTML = `
|
<div class="relative w-20 h-20 rounded-xl overflow-hidden border border-indigo-200 shadow-sm group">
|
||||||
<div class="relative w-20 h-20 rounded-xl overflow-hidden border border-indigo-200 shadow-sm group">
|
<img src="${uploadedImageUrl}" class="w-full h-full object-cover">
|
||||||
<img src="${uploadedImageUrl}" class="w-full h-full object-cover">
|
<div class="absolute inset-0 bg-black/40 hidden group-hover:flex items-center justify-center cursor-pointer" onclick="removeImage()">
|
||||||
<div class="absolute inset-0 bg-black/40 hidden group-hover:flex items-center justify-center cursor-pointer" onclick="removeImage()">
|
<i data-lucide="x" class="w-5 h-5 text-white"></i>
|
||||||
<i data-lucide="x" class="w-5 h-5 text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
</div>
|
||||||
lucide.createIcons();
|
`;
|
||||||
}
|
lucide.createIcons();
|
||||||
|
showToast('图片已就绪', 'success');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast('图片上传失败', 'error');
|
console.error(err);
|
||||||
|
showToast('图片处理失败', 'error');
|
||||||
} finally {
|
} finally {
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user