Explain Codes LogoExplain Codes Logo

Storing Image Data for offline web application (client-side storage database)

javascript
client-side-storage
indexeddb
blob-storage
Anton ShumikhinbyAnton Shumikhin·Mar 7, 2025
TLDR

Use the IndexedDB API for effective client-side image storage. Use createObjectStore for database structure and put to save images encoded to Base64 or as blobs.

// Web archaeologists, let's open the database and create a schema let openDB = indexedDB.open('ImageDB', 1); openDB.onupgradeneeded = () => { let db = openDB.result; db.createObjectStore('Images', { keyPath: 'id' }); }; // Next, let's store our treasure, aka. Base64 image openDB.onsuccess = () => { let db = openDB.result; let store = db.transaction('Images', 'readwrite').objectStore('Images'); store.put({ id: 'img1', content: 'data:image/png;base64,ABC123...' }); }; // Now, let's retrieve our fortune (image) from the vault (database) openDB.onsuccess = () => { let db = openDB.result; let getImage = db.transaction('Images').objectStore('Images').get('img1'); getImage.onsuccess = () => document.getElementById('image').src = getImage.result.content; };

Put in place appropriate error handling with onerror for your database operations.

Client-Side Storage Selection

Select the best storage strategy for offline access by considering storage capacity, browser compatibility, and data type. IndexedDB is a solid choice due to its sizable blob storage capacity and consistent support across modern browsers.

Handling Large Images

When dealing with large 10-20MB PNG images, you'll want to optimize performance by experimenting with compression techniques or tile-based storage, which loads only the visible components of images. This can greatly reduce memory usage and improve fetch time.

Fetching and Storing Data Efficiently

Utilize XMLHttpRequest (XHR2) for efficient blob download as it provides progress events and superior error handling. It's like the express delivery courier for your images. Alternatively, modernize your code using the Fetch API and async/await.

async function fetchAndStoreImage(url, dbStore) { const response = await fetch(url); const blob = await response.blob(); const transaction = dbStore.transaction('Images', 'readwrite'); const store = transaction.objectStore('Images'); store.put({ id: url, content: blob }); }

Remember, for essential resources, service workers and app caches can bring added value to your application.

Web Workers for Better Performance

Introducing Web Workers is akin to having assistants running on a separate thread to expediently fetch (🔄) the paintings (🖼️) or images, without disturbing the main thread. This allows for smooth UI interactions even when fetching and storing images.

// In the background: the diligent web worker self.onmessage = async (e) => { const dbStore = e.data.dbStore; const imageUrl = e.data.imageUrl; await fetchAndStoreImage(imageUrl, dbStore); self.postMessage('Image stored successfully, your majesty!'); };

Use CORS and Canvas to securely fetch images from various domains and manipulate them before storage.

Harmonizing Cross-Browser Compatibility

To ensure a consistent experience across browsers, use IndexedDBShim or LocalForage. These polyfills act as the interpreters, bridging communication gaps and smoothing out inconsistencies.

// LocalForage: your own personal interpreter for browser variations localforage.setItem('myImage', blob).then(() => { console.log('Image stored using the most harmonious backend'); });

Efficient Large Data Set Handling

For large image sets, it's prudent to structure data with SQL queries for BLOB data types, coupled with async iterators or generators to process data in digestible chunks.

async function* getAllImages(db) { const store = db.transaction('Images').objectStore('Images'); let cursor = await store.openCursor(); while (cursor) { yield cursor.value; cursor = await cursor.continue(); } }

Performance Metrics

Fetch and store times are paramount and vary with browser choice. The table below shows difference.

BrowserFetch TimeStore TimeTotal Elapsed Time
Chrome6.551s8.247s13.714s
FireFox0.422s31.519s32.836s
IE 100.668s0.896s3.758s

Remember to test extensively and choose the storage solution that best suits your application.