오프라인 친화적 인 이미지 업로드 시스템 구축-Smashing Magazine
IndexedDB
서비스 작업자 및 배경 동기화 API는 오프라인 친화적 인 이미지 업로드 시스템을 구축하여 대기열을 자동으로 업로드하고 검색하여 오프라인 상태에서도 스트레스가없는 스트레스를 업로드 할 수 있습니다.
따라서 온라인 양식을 작성하고 파일을 업로드하도록 요청합니다. 입력을 클릭하고 데스크탑에서 파일을 선택하고 이동하는 것이 좋습니다. 그러나 무언가가 일어납니다. 네트워크가 떨어지고 파일이 사라지고 파일을 다시 업로드해야합니다. 네트워크 연결 불량 파일을 성공적으로 업로드하려고 불합리한 시간을 소비하게 할 수 있습니다.
사용자 경험을 망치는 것은 네트워크 안정성을 지속적으로 확인하고 업로드를 여러 번 다시 재 시도해야합니다. 우리는 네트워크 연결에 대해 많은 것을 할 수 없지만 개발자로서 항상이 문제와 함께 발생하는 고통을 완화하기 위해 무언가를 할 수 있습니다.
이 문제를 해결할 수있는 방법 중 하나는 이미지 업로드 시스템을 오프라인으로 업로드 할 수있는 방식으로 조정하는 것입니다. 안정적인 네트워크 연결이 필요하지 않습니다그런 다음 시스템이 사용자가 개입하지 않고 네트워크가 안정되면 업로드 프로세스를 재 시도하도록합니다.
이 기사는 구축 방법을 설명하는 데 중점을 둘 것입니다. 오프라인 친화적 인 이미지 업로드 시스템 PWA (Progressive Web Application) 기술 사용 IndexedDB
서비스 작업자 및 배경 동기화 API. 또한이 시스템의 사용자 경험을 향상시키기위한 팁을 간략하게 다룰 것입니다.
오프라인 이미지 업로드 시스템 계획
다음은 오프라인 친화적 인 이미지 업로드 시스템의 흐름도입니다.

흐름도에 표시된 것처럼 프로세스는 다음과 같이 전개됩니다.
- 사용자는 이미지를 선택합니다.
프로세스는 사용자가 이미지를 선택할 수 있도록 시작합니다. - 이미지는 로컬에 저장됩니다
IndexedDB
.
다음으로 시스템은 네트워크 연결을 확인합니다. 네트워크 연결을 사용할 수 있으면 시스템이 이미지를 직접 업로드하여 불필요한 로컬 스토리지 사용을 피합니다. 그러나 네트워크를 사용할 수 없으면 이미지가 저장됩니다.IndexedDB
. - 서비스 작업자는 네트워크가 복원되면 감지합니다.
이미지가 저장되어 있습니다IndexedDB
시스템은 다음 단계를 계속하기 위해 네트워크 연결이 복원되는 시점을 감지 할 때까지 기다립니다. - 배경 동기화 프로세스가 업로드 중입니다.
연결이 복원되는 순간 시스템은 이미지를 다시 업로드하려고합니다. - 파일이 성공적으로 업로드되었습니다.
이미지가 업로드되는 순간 시스템은 저장된 로컬 사본을 제거합니다.IndexedDB
.
시스템 구현
시스템 구현의 첫 번째 단계는 사용자가 이미지를 선택할 수 있도록하는 것입니다. 이를 달성 할 수있는 방법에는 여러 가지가 있습니다.
나는 당신이 둘 다 사용하는 것이 좋습니다. 일부 사용자는 드래그 앤 드롭 인터페이스를 사용하는 것을 선호하고 다른 사용자는 이미지를 업로드하는 유일한 방법은 요소. 두 옵션을 모두 갖추면 사용자 경험을 향상시키는 데 도움이됩니다. 또한 클립 보드 API를 사용하여 브라우저에 직접 이미지를 붙여 넣을 수있는 것을 고려할 수도 있습니다.
서비스 작업자 등록
이 솔루션의 중심에는 서비스 작업자가 있습니다. 우리의 서비스 근로자는 이미지를 IndexedDB
인터넷 연결이 복원 될 때 저장, 업로드하고 IndexedDB
이미지가 업로드되었을 때 저장하십시오.
서비스 작업자를 사용하려면 먼저 하나를 등록해야합니다.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(reg => console.log('Service Worker registered', reg))
.catch(err => console.error('Service Worker registration failed', err));
}
네트워크 연결 확인
우리가 해결하려는 문제는 신뢰할 수없는 네트워크 연결. 이 문제가 존재하지 않으면 아무것도 해결하려고 할 필요가 없습니다. 따라서 이미지가 선택되면 동기화 이벤트를 등록하고 이미지를 저장하기 전에 사용자가 신뢰할 수있는 인터넷 연결이 있는지 확인해야합니다. IndexedDB
.
function uploadImage() {
if (navigator.onLine) {
// Upload Image
} else {
// register Sync Event
// Store Images in IndexedDB
}
}
메모: 나는 단지 사용하고 있습니다 navigator.onLine
시스템의 작동 방식을 보여주는 속성. 그만큼 navigator.onLine
속성은 신뢰할 수 없는사용자가 인터넷에 연결되어 있는지 확인하기 위해 사용자 정의 솔루션을 생각해내는 것이 좋습니다. 이를 수행 할 수있는 한 가지 방법은 Ping 요청을 생성 한 서버 엔드 포인트로 보내는 것입니다.
동기화 이벤트 등록
네트워크 테스트가 실패하면 다음 단계는 동기화 이벤트를 등록하는 것입니다. 인터넷 연결 불량으로 인해 시스템이 이미지를 업로드하지 못하는 시점에서 SYNC 이벤트를 등록해야합니다.
async function registerSyncEvent() {
if ('SyncManager' in window) {
const registration = await navigator.serviceWorker.ready;
await registration.sync.register('uploadImages');
console.log('Background Sync registered');
}
}
SYNC 이벤트를 등록한 후에는 서비스 작업자에서 이벤트를 들어야합니다.
self.addEventListener('sync', (event) => {
if (event.tag === 'uploadImages') {
event.waitUntil(sendImages());
}
});
그만큼 sendImages
기능은 이미지를 검색하는 비동기 프로세스가 될 것입니다. IndexedDB
서버에 업로드하십시오. 이것이 바로 모양입니다.
async function sendImages() {
try {
// await image retrieval and upload
} catch (error) {
// throw error
}
}
데이터베이스 열기
이미지를 로컬로 저장하기 위해해야 할 첫 번째 일은 IndexedDB
가게. 아래 코드에서 볼 수 있듯이 우리는 데이터베이스 인스턴스를 저장하는 글로벌 변수. 이를 수행하는 이유는 이후에 이미지를 검색하고 싶을 때 IndexedDB
데이터베이스를 다시 열기 위해 코드를 작성할 필요가 없습니다.
let database; // Global variable to store the database instance
function openDatabase() {
return new Promise((resolve, reject) => {
if (database) return resolve(database); // Return existing database instance
const request = indexedDB.open("myDatabase", 1);
request.onerror = (event) => {
console.error("Database error:", event.target.error);
reject(event.target.error); // Reject the promise on error
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Create the "images" object store if it doesn't exist.
if (!db.objectStoreNames.contains("images")) {
db.createObjectStore("images", { keyPath: "id" });
}
console.log("Database setup complete.");
};
request.onsuccess = (event) => {
database = event.target.result; // Store the database instance globally
resolve(database); // Resolve the promise with the database instance
};
});
}
INDEXEDDB에 이미지를 저장합니다
함께 IndexedDB
개방형, 이제 이미지를 저장할 수 있습니다.
이제 더 쉬운 솔루션이 왜
localStorage
이 목적으로 사용되지 않았습니다.그 이유는 그 이유입니다
IndexedDB
비동기 적으로 작동하며 기본 JavaScript 스레드를 차단하지 않지만localStorage
동기식으로 실행되며 JavaScript 메인 스레드를 사용하는 경우 차단할 수 있습니다.
이미지를 저장하는 방법은 다음과 같습니다 IndexedDB
:
async function storeImages(file) {
// Open the IndexedDB database.
const db = await openDatabase();
// Create a transaction with read and write access.
const transaction = db.transaction("images", "readwrite");
// Access the "images" object store.
const store = transaction.objectStore("images");
// Define the image record to be stored.
const imageRecord = {
id: IMAGE_ID, // a unique ID
image: file // Store the image file (Blob)
};
// Add the image record to the store.
const addRequest = store.add(imageRecord);
// Handle successful addition.
addRequest.onsuccess = () => console.log("Image added successfully!");
// Handle errors during insertion.
addRequest.onerror = (e) => console.error("Error storing image:", e.target.error);
}
이미지가 저장되고 배경 동기화가 설정되면 네트워크 연결이 복원 될 때마다 시스템이 이미지를 업로드 할 준비가되었습니다.
이미지 검색 및 업로드
네트워크 연결이 복원되면 동기화 이벤트가 시작되고 서비스 작업자가 이미지를 검색합니다. IndexedDB
그리고 그것을 업로드하십시오.
async function retrieveAndUploadImage(IMAGE_ID) {
try {
const db = await openDatabase(); // Ensure the database is open
const transaction = db.transaction("images", "readonly");
const store = transaction.objectStore("images");
const request = store.get(IMAGE_ID);
request.onsuccess = function (event) {
const image = event.target.result;
if (image) {
// upload Image to server here
} else {
console.log("No image found with ID:", IMAGE_ID);
}
};
request.onerror = () => {
console.error("Error retrieving image.");
};
} catch (error) {
console.error("Failed to open database:", error);
}
}
indexeddb 데이터베이스 삭제
이미지가 업로드되면 IndexedDB
상점은 더 이상 필요하지 않습니다. 따라서 스토리지를 확보하려면 컨텐츠와 함께 삭제해야합니다.
function deleteDatabase() {
// Check if there's an open connection to the database.
if (database) {
database.close(); // Close the database connection
console.log("Database connection closed.");
}
// Request to delete the database named "myDatabase".
const deleteRequest = indexedDB.deleteDatabase("myDatabase");
// Handle successful deletion of the database.
deleteRequest.onsuccess = function () {
console.log("Database deleted successfully!");
};
// Handle errors that occur during the deletion process.
deleteRequest.onerror = function (event) {
console.error("Error deleting database:", event.target.error);
};
// Handle cases where the deletion is blocked (e.g., if there are still open connections).
deleteRequest.onblocked = function () {
console.warn("Database deletion blocked. Close open connections and try again.");
};
}
이를 통해 전체 프로세스가 완료되었습니다!
고려 사항 및 제한
오프라인 업로드를 지원함으로써 경험을 향상시키는 데 도움이되는 많은 일을했지만 시스템에는 제한이 없습니다. 이 솔루션이 귀하의 요구에 미치지 못하는 곳을 아는 것이 가치가 있기 때문에 구체적으로 전화를 걸겠다고 생각했습니다.
- 신뢰할 수있는 인터넷 연결 감지가 없습니다
JavaScript는 온라인 상태를 감지하는 완벽한 방법을 제공하지 않습니다. 이러한 이유로 온라인 상태를 감지하기위한 사용자 정의 솔루션을 제시해야합니다. - 크롬 전용 용액
배경 동기화 API는 현재 크롬 기반 브라우저로 제한됩니다. 따라서이 솔루션은 크롬 브라우저에 의해서만 지원됩니다. 즉, 비 초간 브라우저에 대부분의 사용자가있는 경우보다 강력한 솔루션이 필요합니다. IndexedDB
저장 정책
브라우저는 저장소 제한 및 퇴거 정책을 부과합니다IndexedDB
. 예를 들어, 사파리에서 데이터가 저장되었습니다IndexedDB
사용자가 웹 사이트와 상호 작용하지 않으면 수명이 7 일입니다. 이것은 Safari를 지원하는 Background Sync API에 대한 대안을 생각해 내면 명심해야 할 것입니다.
사용자 경험을 향상시킵니다
전체 프로세스가 백그라운드에서 발생하므로 이미지가 저장되거나 업로드되기를 기다리거나 성공적으로 업로드되었을 때 사용자에게 알리는 방법이 필요합니다. 특정 구현 UI 요소 이를 위해 실제로 사용자의 경험을 향상시킬 것입니다. 이러한 UI 요소에는 토스트 알림, 스피너 (활성 프로세스 표시), 진행률 표시 줄 (상태 진행률 표시), 네트워크 상태 표시기 또는 재 시도 및 취소 옵션을 제공하는 버튼을 업로드하는 상태 표시기가 포함될 수 있습니다.
마무리
인터넷 연결 불량은 웹 응용 프로그램의 사용자 경험을 방해 할 수 있습니다. 그러나 PWA 기술을 활용하여 IndexedDB
서비스 작업자 및 배경 동기화 API, 개발자는 사용자, 특히 신뢰할 수없는 인터넷 연결이있는 영역의 웹 애플리케이션의 신뢰성을 향상시키는 데 도움이 될 수 있습니다.

(GG, YK)
Post Comment