File size: 7,065 Bytes
2717123 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
// static/js/db.js
const DB_NAME = 'AlphaChatFileStore';
const STORE_NAME = 'files';
// *** قدم 1: نسخه دیتابیس را افزایش میدهیم تا فرآیند ارتقا فعال شود ***
const DB_VERSION = 2;
let db;
// 1. مقداردهی اولیه و باز کردن دیتابیس
export function initDB() {
return new Promise((resolve, reject) => {
console.log(`در حال تلاش برای باز کردن دیتابیس ${DB_NAME} با نسخه ${DB_VERSION}...`);
const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onerror = (event) => {
console.error("خطای حیاتی در باز کردن IndexedDB:", event.target.error);
reject("خطای دیتابیس. لطفا از فعال بودن کوکیها و فضای ذخیرهسازی مرورگر اطمینان حاصل کنید.");
};
request.onsuccess = (event) => {
db = event.target.result;
console.log("IndexedDB با موفقیت باز و آماده استفاده است.");
resolve(db);
};
// این تابع فقط زمانی اجرا میشود که دیتابیس برای اولین بار ساخته شود یا نسخه آن (DB_VERSION) افزایش یابد.
request.onupgradeneeded = (event) => {
console.log("رویداد onupgradeneeded فعال شد. در حال ارتقا ساختار دیتابیس...");
const db = event.target.result;
// *** قدم 2: منطق ارتقا را هوشمند میکنیم ***
// ابتدا بررسی میکنیم که آیا ساختار قدیمی (و اشتباه) وجود دارد یا نه
if (db.objectStoreNames.contains(STORE_NAME)) {
// اگر وجود داشت، آن را حذف میکنیم تا راه برای ساختار جدید باز شود.
db.deleteObjectStore(STORE_NAME);
console.log("Object store قدیمی 'files' پیدا و برای ارتقا حذف شد.");
}
// حالا ساختار جدید و صحیح را ایجاد میکنیم.
// با حذف keyPath، به IndexedDB اجازه میدهیم کلید را به صورت خودکار و خارج از آبجکت مدیریت کند.
// این کار مشکل اصلی شما را به طور قطعی حل میکند.
const store = db.createObjectStore(STORE_NAME, { autoIncrement: true });
// یک ایندکس برای جستجوی فایلها بر اساس زمان ایجاد میکنیم.
store.createIndex('timestamp', 'timestamp', { unique: false });
console.log("Object store جدید و صحیح 'files' با موفقیت ساخته شد.");
};
});
}
// 2. ذخیره کردن یک فایل در دیتابیس
export function storeFile(file) {
return new Promise((resolve, reject) => {
if (!db) {
// این حالت نباید رخ دهد چون main.js منتظر اتمام initDB میماند.
reject("دیتابیس هنوز مقداردهی اولیه نشده است.");
return;
}
const transaction = db.transaction([STORE_NAME], 'readwrite');
const store = transaction.objectStore(STORE_NAME);
const fileRecord = {
file: file,
name: file.name,
type: file.type,
timestamp: Date.now()
};
const request = store.add(fileRecord);
request.onsuccess = (event) => {
// event.target.result حاوی کلید (ID) اختصاص داده شده به رکورد جدید است.
resolve(event.target.result);
};
request.onerror = (event) => {
console.error("خطا در ذخیره فایل در IndexedDB:", event.target.error);
reject("ذخیره فایل در دیتابیس محلی ناموفق بود.");
};
});
}
// 3. بازیابی یک فایل از دیتابیس با استفاده از ID
export function getFile(id) {
return new Promise((resolve, reject) => {
if (!db) {
reject("دیتابیس مقداردهی اولیه نشده است.");
return;
}
// کلیدهای تولید شده توسط autoIncrement همیشه عددی هستند.
// این تبدیل، اطمینان میدهد که حتی اگر ID به صورت رشته ذخیره شده باشد، به درستی بازیابی شود.
const numericId = typeof id === 'string' ? parseInt(id, 10) : id;
if (isNaN(numericId)) {
reject("ID فایل برای بازیابی نامعتبر است.");
return;
}
const transaction = db.transaction([STORE_NAME], 'readonly');
const store = transaction.objectStore(STORE_NAME);
const request = store.get(numericId);
request.onsuccess = (event) => {
if (event.target.result) {
// خود فایل که یک Blob است را باز میگردانیم.
resolve(event.target.result.file);
} else {
reject("فایلی با این ID در دیتابیس محلی یافت نشد.");
}
};
request.onerror = (event) => {
console.error("خطا در بازیابی فایل:", event.target.error);
reject("بازیابی فایل ناموفق بود.");
};
});
}
// 4. پاک کردن فایلهای قدیمیتر از یک هفته
export function cleanupOldFiles() {
return new Promise((resolve, reject) => {
if (!db) {
reject("دیتابیس مقداردهی اولیه نشده است.");
return;
}
const transaction = db.transaction([STORE_NAME], 'readwrite');
const store = transaction.objectStore(STORE_NAME);
const index = store.index('timestamp');
const oneWeekAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
const range = IDBKeyRange.upperBound(oneWeekAgo);
const request = index.openCursor(range);
let deletedCount = 0;
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
cursor.delete();
deletedCount++;
cursor.continue();
} else {
if(deletedCount > 0) console.log(`${deletedCount} فایل قدیمی و منقضی شده از IndexedDB پاک شد.`);
resolve();
}
};
request.onerror = (event) => {
console.error("خطا در پاکسازی فایلهای قدیمی:", event.target.error);
reject("پاکسازی فایلهای قدیمی ناموفق بود.");
};
});
} |