重构: 优化indexedDBStorage中的图像存储和uiController中的URL处理逻辑,确保Blob URL和Base64数据的一致性。
This commit is contained in:
205
script.js
205
script.js
@@ -58,6 +58,12 @@ const utils = {
|
||||
return base64Data;
|
||||
}
|
||||
|
||||
// 检查是否是base64数据格式
|
||||
if (!base64Data.startsWith('data:image/')) {
|
||||
console.warn('Not a valid base64 image format, returning original data');
|
||||
return base64Data;
|
||||
}
|
||||
|
||||
// 提取base64数据的MIME类型和纯数据部分
|
||||
const parts = base64Data.split(';base64,');
|
||||
if (parts.length !== 2) {
|
||||
@@ -399,15 +405,43 @@ const indexedDBStorage = {
|
||||
}
|
||||
|
||||
try {
|
||||
const transaction = this.db.transaction([CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES], 'readwrite');
|
||||
const store = transaction.objectStore(CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES);
|
||||
|
||||
// 检查是否是Blob URL,如果是则获取原始base64数据
|
||||
// 首先处理图像URL,获取要存储的数据
|
||||
let storedUrl = imageUrl;
|
||||
if (imageUrl.startsWith('blob:') && imageUrl._originalBase64) {
|
||||
storedUrl = imageUrl._originalBase64;
|
||||
console.log('Storing original base64 data for image');
|
||||
} else if (imageUrl.startsWith('data:image/')) {
|
||||
// 已经是base64格式,直接存储
|
||||
console.log('Image is already in base64 format, storing directly');
|
||||
} else if (imageUrl.startsWith('blob:')) {
|
||||
// Blob URL没有原始base64数据,需要从Blob URL中提取base64数据
|
||||
console.warn('Blob URL has no original base64 data, attempting to extract base64 data from Blob');
|
||||
try {
|
||||
// 通过fetch获取Blob数据,然后转换为base64
|
||||
const response = await fetch(imageUrl);
|
||||
const blob = await response.blob();
|
||||
|
||||
// 将Blob转换为base64
|
||||
const reader = new FileReader();
|
||||
const base64Promise = new Promise((resolve, reject) => {
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onerror = reject;
|
||||
});
|
||||
reader.readAsDataURL(blob);
|
||||
|
||||
storedUrl = await base64Promise;
|
||||
console.log('Successfully extracted base64 data from Blob URL');
|
||||
} catch (error) {
|
||||
console.error('Failed to extract base64 data from Blob URL:', error);
|
||||
// 如果转换失败,仍然存储原始URL,但记录警告
|
||||
console.warn('Storing original Blob URL, which may cause issues after page reload');
|
||||
}
|
||||
}
|
||||
|
||||
// 现在创建事务并存储数据
|
||||
const transaction = this.db.transaction([CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES], 'readwrite');
|
||||
const store = transaction.objectStore(CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES);
|
||||
|
||||
const image = {
|
||||
imageId: imageId,
|
||||
url: storedUrl,
|
||||
@@ -717,7 +751,9 @@ const apiService = {
|
||||
// 提取图像数据并转换为Blob URL,但保留原始base64数据
|
||||
if (choice.message.images) {
|
||||
choice.message.images.forEach(img => {
|
||||
const blobUrl = utils.base64ToBlobUrl(img.image_url.url);
|
||||
// 确保原始数据是base64格式
|
||||
const originalBase64 = img.image_url.url;
|
||||
const blobUrl = utils.base64ToBlobUrl(originalBase64);
|
||||
images.push(blobUrl);
|
||||
});
|
||||
}
|
||||
@@ -821,7 +857,23 @@ const uiController = {
|
||||
const imageId = Date.now() + Math.random();
|
||||
|
||||
// 确保imageUrl是Blob URL用于显示,但保存原始URL用于存储
|
||||
const displayUrl = imageUrl.startsWith('blob:') ? imageUrl : utils.base64ToBlobUrl(imageUrl);
|
||||
let displayUrl;
|
||||
let originalUrl = imageUrl; // 原始URL,可能是base64或Blob URL
|
||||
|
||||
if (imageUrl.startsWith('blob:')) {
|
||||
displayUrl = imageUrl;
|
||||
} else if (imageUrl.startsWith('data:image/')) {
|
||||
// 这是base64数据,转换为Blob URL
|
||||
displayUrl = utils.base64ToBlobUrl(imageUrl);
|
||||
} else {
|
||||
// 其他格式,直接使用
|
||||
displayUrl = imageUrl;
|
||||
}
|
||||
|
||||
// 确保Blob URL有原始base64数据
|
||||
if (displayUrl.startsWith('blob:') && !displayUrl._originalBase64 && originalUrl.startsWith('data:image/')) {
|
||||
displayUrl._originalBase64 = originalUrl;
|
||||
}
|
||||
|
||||
imageDiv.innerHTML = `
|
||||
<img src="${displayUrl}" alt="Generated Image" loading="lazy" class="generated-image">
|
||||
@@ -935,7 +987,23 @@ const uiController = {
|
||||
placeholder.id = '';
|
||||
|
||||
// 确保imageUrl是Blob URL用于显示,但保存原始URL用于存储
|
||||
const displayUrl = imageUrl.startsWith('blob:') ? imageUrl : utils.base64ToBlobUrl(imageUrl);
|
||||
let displayUrl;
|
||||
let originalUrl = imageUrl; // 原始URL,可能是base64或Blob URL
|
||||
|
||||
if (imageUrl.startsWith('blob:')) {
|
||||
displayUrl = imageUrl;
|
||||
} else if (imageUrl.startsWith('data:image/')) {
|
||||
// 这是base64数据,转换为Blob URL
|
||||
displayUrl = utils.base64ToBlobUrl(imageUrl);
|
||||
} else {
|
||||
// 其他格式,直接使用
|
||||
displayUrl = imageUrl;
|
||||
}
|
||||
|
||||
// 确保Blob URL有原始base64数据
|
||||
if (displayUrl.startsWith('blob:') && !displayUrl._originalBase64 && originalUrl.startsWith('data:image/')) {
|
||||
displayUrl._originalBase64 = originalUrl;
|
||||
}
|
||||
|
||||
placeholder.innerHTML = `
|
||||
<img src="${displayUrl}" alt="Generated Image" loading="lazy" class="generated-image">
|
||||
@@ -1057,7 +1125,17 @@ const uiController = {
|
||||
currentImageIndex = generatedImages.findIndex(img => img.url === imageUrl);
|
||||
|
||||
// 设置图像源 - 确保正确处理base64和Blob URL
|
||||
const displayUrl = imageUrl.startsWith('blob:') ? imageUrl : utils.base64ToBlobUrl(imageUrl);
|
||||
let displayUrl;
|
||||
if (imageUrl.startsWith('blob:')) {
|
||||
displayUrl = imageUrl;
|
||||
} else if (imageUrl.startsWith('data:image/')) {
|
||||
// 这是base64数据,转换为Blob URL
|
||||
displayUrl = utils.base64ToBlobUrl(imageUrl);
|
||||
} else {
|
||||
// 其他格式,直接使用
|
||||
displayUrl = imageUrl;
|
||||
}
|
||||
|
||||
modalImage.src = displayUrl;
|
||||
modalImage.onerror = function() {
|
||||
utils.showNotification('图像加载失败', 'danger');
|
||||
@@ -1066,7 +1144,7 @@ const uiController = {
|
||||
// 设置下载按钮功能
|
||||
if (downloadButton) {
|
||||
downloadButton.onclick = function() {
|
||||
app.downloadImage(imageUrl);
|
||||
app.downloadImage(generatedImages[currentImageIndex].url);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1086,7 +1164,10 @@ const uiController = {
|
||||
|
||||
// 重新加载当前图像
|
||||
if (currentImageIndex >= 0 && currentImageIndex < generatedImages.length) {
|
||||
modalImage.src = generatedImages[currentImageIndex].url;
|
||||
const displayUrl = generatedImages[currentImageIndex].url.startsWith('blob:') ?
|
||||
generatedImages[currentImageIndex].url :
|
||||
utils.base64ToBlobUrl(generatedImages[currentImageIndex].url);
|
||||
modalImage.src = displayUrl;
|
||||
}
|
||||
|
||||
this.updateNavigationButtons();
|
||||
@@ -1285,12 +1366,21 @@ const uiController = {
|
||||
// 更新图片
|
||||
const modalImage = document.getElementById('viewerModalImage');
|
||||
const deleteButton = document.getElementById('viewerDeleteImage');
|
||||
const downloadButton = document.getElementById('viewerDownloadImage');
|
||||
|
||||
if (modalImage && generatedImages[currentImageIndex]) {
|
||||
// 确保正确处理base64和Blob URL
|
||||
const displayUrl = generatedImages[currentImageIndex].url.startsWith('blob:') ?
|
||||
generatedImages[currentImageIndex].url :
|
||||
utils.base64ToBlobUrl(generatedImages[currentImageIndex].url);
|
||||
const imageUrl = generatedImages[currentImageIndex].url;
|
||||
let displayUrl;
|
||||
if (imageUrl.startsWith('blob:')) {
|
||||
displayUrl = imageUrl;
|
||||
} else if (imageUrl.startsWith('data:image/')) {
|
||||
// 这是base64数据,转换为Blob URL
|
||||
displayUrl = utils.base64ToBlobUrl(imageUrl);
|
||||
} else {
|
||||
// 其他格式,直接使用
|
||||
displayUrl = imageUrl;
|
||||
}
|
||||
modalImage.src = displayUrl;
|
||||
|
||||
// 更新删除按钮对应的图像ID
|
||||
@@ -1306,9 +1396,17 @@ const uiController = {
|
||||
currentImageIndex = generatedImages.length - 1;
|
||||
}
|
||||
if (currentImageIndex >= 0 && currentImageIndex < generatedImages.length) {
|
||||
const newDisplayUrl = generatedImages[currentImageIndex].url.startsWith('blob:') ?
|
||||
generatedImages[currentImageIndex].url :
|
||||
utils.base64ToBlobUrl(generatedImages[currentImageIndex].url);
|
||||
const imageUrl = generatedImages[currentImageIndex].url;
|
||||
let newDisplayUrl;
|
||||
if (imageUrl.startsWith('blob:')) {
|
||||
newDisplayUrl = imageUrl;
|
||||
} else if (imageUrl.startsWith('data:image/')) {
|
||||
// 这是base64数据,转换为Blob URL
|
||||
newDisplayUrl = utils.base64ToBlobUrl(imageUrl);
|
||||
} else {
|
||||
// 其他格式,直接使用
|
||||
newDisplayUrl = imageUrl;
|
||||
}
|
||||
modalImage.src = newDisplayUrl;
|
||||
deleteButton.onclick = arguments.callee;
|
||||
}
|
||||
@@ -1316,6 +1414,13 @@ const uiController = {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 更新下载按钮对应的图像URL
|
||||
if (downloadButton) {
|
||||
downloadButton.onclick = function() {
|
||||
app.downloadImage(generatedImages[currentImageIndex].url);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 更新导航按钮状态
|
||||
@@ -1382,7 +1487,16 @@ const uiController = {
|
||||
const preview = document.getElementById('imagePreview');
|
||||
|
||||
// 确保图像数据是Blob URL用于显示,但保持原始数据用于其他操作
|
||||
const displayUrl = imageData.data.startsWith('blob:') ? imageData.data : utils.base64ToBlobUrl(imageData.data);
|
||||
let displayUrl;
|
||||
if (imageData.data.startsWith('blob:')) {
|
||||
displayUrl = imageData.data;
|
||||
} else if (imageData.data.startsWith('data:image/')) {
|
||||
// 这是base64数据,转换为Blob URL
|
||||
displayUrl = utils.base64ToBlobUrl(imageData.data);
|
||||
} else {
|
||||
// 其他格式,直接使用
|
||||
displayUrl = imageData.data;
|
||||
}
|
||||
|
||||
preview.innerHTML = `
|
||||
<div class="card h-100">
|
||||
@@ -1508,8 +1622,16 @@ const uiController = {
|
||||
const imageDiv = document.createElement('div');
|
||||
imageDiv.className = 'image-item fade-in';
|
||||
|
||||
// 确保从IndexedDB加载的base64数据转换为Blob URL用于显示
|
||||
const displayUrl = img.url.startsWith('blob:') ? img.url : utils.base64ToBlobUrl(img.url);
|
||||
// 从IndexedDB加载的数据应该是base64格式,直接使用
|
||||
// 如果是base64数据,创建一个新的Blob URL用于显示
|
||||
let displayUrl;
|
||||
if (img.url.startsWith('data:image/')) {
|
||||
// 这是base64数据
|
||||
displayUrl = utils.base64ToBlobUrl(img.url);
|
||||
} else {
|
||||
// 这可能是其他格式的URL,直接使用
|
||||
displayUrl = img.url;
|
||||
}
|
||||
|
||||
imageDiv.innerHTML = `
|
||||
<img src="${displayUrl}" alt="Generated Image" loading="lazy" class="generated-image">
|
||||
@@ -1881,7 +2003,13 @@ const app = {
|
||||
|
||||
// 为每个图像添加新的图像项
|
||||
result.response.images.forEach((img, imgIndex) => {
|
||||
uiController.addGeneratedImage(img);
|
||||
// 确保Blob URL有原始base64数据
|
||||
if (img.startsWith('blob:') && img._originalBase64) {
|
||||
uiController.addGeneratedImage(img);
|
||||
} else {
|
||||
// 如果没有原始base64数据,需要从API响应中获取
|
||||
uiController.addGeneratedImage(img);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 只有一个图像,直接替换占位符
|
||||
@@ -2035,7 +2163,7 @@ const app = {
|
||||
utils.showNotification('下载图像失败', 'danger');
|
||||
});
|
||||
} else {
|
||||
// 如果是普通URL,直接下载
|
||||
// 如果是base64数据,直接下载
|
||||
const link = document.createElement('a');
|
||||
link.href = imageUrl;
|
||||
link.download = `generated-image-${Date.now()}.png`;
|
||||
@@ -2056,10 +2184,37 @@ const app = {
|
||||
// 逐个下载图像
|
||||
generatedImages.forEach((img, index) => {
|
||||
setTimeout(() => {
|
||||
const link = document.createElement('a');
|
||||
link.href = img.url;
|
||||
link.download = `generated-image-${Date.now()}-${index + 1}.png`;
|
||||
link.click();
|
||||
// 使用与单个图像下载相同的逻辑
|
||||
if (img.url.startsWith('blob:') && img.url._originalBase64) {
|
||||
// 使用原始base64数据下载
|
||||
const link = document.createElement('a');
|
||||
link.href = img.url._originalBase64;
|
||||
link.download = `generated-image-${Date.now()}-${index + 1}.png`;
|
||||
link.click();
|
||||
} else if (img.url.startsWith('blob:')) {
|
||||
// 如果没有原始base64数据,通过fetch获取Blob数据
|
||||
fetch(img.url)
|
||||
.then(response => response.blob())
|
||||
.then(blob => {
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = `generated-image-${Date.now()}-${index + 1}.png`;
|
||||
link.click();
|
||||
// 清理临时URL
|
||||
setTimeout(() => URL.revokeObjectURL(url), 100);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error downloading image:', error);
|
||||
utils.showNotification('下载图像失败', 'danger');
|
||||
});
|
||||
} else {
|
||||
// 如果是base64数据,直接下载
|
||||
const link = document.createElement('a');
|
||||
link.href = img.url;
|
||||
link.download = `generated-image-${Date.now()}-${index + 1}.png`;
|
||||
link.click();
|
||||
}
|
||||
|
||||
// 最后一个图像下载完成后显示通知
|
||||
if (index === generatedImages.length - 1) {
|
||||
|
||||
Reference in New Issue
Block a user