इवेंट-फोटो ऐप्स के डेवलपर्स के पास अब भीड़भाड़ वाले वेन्यू में ब्राउज़र अपलोड को चालू रखने के लिए एक ठोस चेकलिस्ट है। एक अकेला उपयोगकर्ता वाई-फाई से सेलुलर पर स्विच कर सकता है जबकि दर्जनों डिवाइस एक ही हॉटस्पॉट के लिए प्रतिस्पर्धा कर रहे हों। यह गाइड दिखाती है कि "अपलोड पूरा हुआ" (upload complete) टोस्ट दिखने के बाद भी फोटो को गायब होने से कैसे रोका जाए, भले ही मेहमान फोन लॉक कर दे या नेटवर्क में रुकावट आए।

शादियों और त्योहारों में साधारण अपलोड क्यों विफल हो जाते हैं

ऑफिस में, एक लैपटॉप स्थिर ईथरनेट (Ethernet) लिंक पर होता है और एक अकेला उपयोगकर्ता "भेजें" (send) पर क्लिक करता है। लेकिन शादी के रिसेप्शन या म्यूजिक फेस्टिवल में, यही क्रिया समस्याओं की एक श्रृंखला शुरू कर सकती है: मेहमान समारोह हॉल से पार्किंग स्थल की ओर चल देता है, सैकड़ों फोन के कारण राउटर जवाब दे देता है, या फोन वाई-फाई छोड़ देता है और सेलुलर पर आ जाता है। ब्राउज़र ने सर्वर को हर बाइट स्ट्रीम कर दिया हो सकता है, लेकिन सर्वर ने अभी तक फ़ाइल को स्टोरेज में सुरक्षित (commit) नहीं किया होता है। यदि UI प्रोग्रेस बार के 100% पहुँचते ही सफलता घोषित कर देता है, तो मेहमान फोटो डिलीट कर सकता है, जिससे आयोजक के पास एक अधूरी फ़ाइल रह जाएगी।

"बस अपलोड करें" की छिपी हुई लागत

एक सरल दृष्टिकोण अपलोड को एक एकल HTTP POST के रूप में मानता है। यह तब काम करता है जब कनेक्शन स्थिर हो, लेकिन भीड़भाड़ वाले नेटवर्क पर प्रत्येक रुकावट पूरी फ़ाइल को फिर से शुरू करने के लिए मजबूर करती है। जब दर्जनों फोन एक साथ फिर से कोशिश करते हैं, तो उपयोगकर्ता निराश हो जाते हैं और बैंडविड्थ में अचानक उछाल (spike) आता है। फ़ाइल को टुकड़ों (chunks) में विभाजित करना और प्रत्येक हिस्से को ट्रैक करना जटिलता तो बढ़ाता है, लेकिन इसका लाभ एक अनुमानित, कम ओवरहेड वाला ट्रांसफर है जो नेटवर्क स्विच के दौरान भी बना रहता है।

एक रिज़्यूमेबल (resumable), चंक्ड (chunked) अपलोड सिस्टम बनाना

नीचे एक व्यावहारिक, चरण-दर-चरण विधि दी गई है।

1. ब्राउज़र से कोई भी डेटा बाहर जाने से पहले एक अपलोड ID जेनरेट करें

स्थानीय रूप से एक यूनिवर्सल यूनिक आइडेंटिफायर (UUID) बनाएं और उसे पहले अनुरोध के रूप में सर्वर पर भेजें। सर्वर उस ID के तहत एक सेशन रिकॉर्ड करता है। यदि ब्राउज़र बाद में टाइमआउट के कारण फिर से कोशिश करता है, तो वह उसी UUID को शामिल करता है, जिससे सर्वर सेशन को पहचान पाता है और डुप्लिकेट एंट्री से बच जाता है। यह वर्कफ़्लो को आइडम्पोटेंट (idempotent) बनाता है—उसी अनुरोध को दोहराने का कोई प्रतिकूल प्रभाव नहीं पड़ता है।

2. फ़ाइल को 5 – 10 MB के चंक्स (chunks) में विभाजित करें

चंक का आकार एक समझौता (trade-off) है। छोटे चंक्स (1 MB से कम) HTTP अनुरोधों की संख्या और उससे जुड़े हेडर ओवरहेड को बढ़ाते हैं। बहुत बड़े चंक्स किसी भी रुकावट को महंगा बना देते हैं क्योंकि क्लाइंट को एक बड़ा हिस्सा फिर से भेजना पड़ता है। सामान्य फोटो और छोटे वीडियो के लिए, 5 – 10 MB एक संतुलन बनाता है: प्रत्येक अनुरोध UI को रिस्पॉन्सिव रखने के लिए पर्याप्त तेज़ी से पूरा होता है, फिर भी अनुरोधों की संख्या प्रबंधनीय रहती है।

3. समानांतर (parallel) अपलोड की संख्या सीमित करें

मोबाइल ब्राउज़र कई कनेक्शन खोल सकते हैं, लेकिन भीड़भाड़ वाले वाई-फाई नेटवर्क पर प्रत्येक अतिरिक्त स्ट्रीम सीमित बैंडविड्थ के लिए प्रतिस्पर्धा करती है। आठ प्रतिस्पर्धी स्ट्रीम के मुकाबले दो स्थिर स्ट्रीम बेहतर हैं। कम बैंडविड्थ वाली स्थितियों का पता लगाने और ऑटोमैटिक रूप से कन्करेंसी (concurrency) कम करने के लिए navigator.connection API का उपयोग करें।

4. IndexedDB में अपलोड स्टेट को सुरक्षित रखें

अपलोड ID, पहले से भेजे गए चंक्स की सूची और सर्वर द्वारा स्वीकार किए गए किसी भी ऑफसेट (offsets) को ब्राउज़र के IndexedDB में स्टोर करें। यदि पेज रीलोड होता है या उपयोगकर्ता टैब बंद कर देता है, तो क्लाइंट अगली बार लोड होने पर स्टेट को रिकवर कर सकता है। जब उपयोगकर्ता पेज को फिर से खोलता है, तो उन्हें वही फ़ाइल चुनने के लिए कहें; स्टोर किया गया मेटाडेटा अपलोड को फिर से शुरू करने के बजाय अंतिम कन्फर्म किए गए चंक से फिर से शुरू करने की अनुमति देता है।

5. केवल navigator.onLine नहीं, बल्कि वास्तविक नेटवर्क परिवर्तनों का पता लगाएं

navigator.onLine फ्लैग अक्सर तब भी "online" रिपोर्ट करता है जब कनेक्शन अनुपयोगी हो। इसके बजाय, प्रत्येक चंक के लिए एक छोटा रिक्वेस्ट टाइमआउट (जैसे, 5 सेकंड) सेट करें। यदि टाइमआउट होता है, तो नेटवर्क को डाउन मानें। जब कनेक्टिविटी वापस आ जाए, तो सर्वर से उन चंक्स की सूची पूछें जो उसके पास पहले से हैं, और फिर केवल छूटे हुए हिस्सों को अपलोड करना जारी रखें। यह संक्षिप्त आउटेज के बाद डुप्लिकेट डेटा भेजने से बचाता है।

6. रिट्राइ (retries) के लिए जिटर (jitter) के साथ एक्सपोनेंशियल बैकऑफ़ (exponential backoff) लागू करें

जब कई मेहमानों के डिवाइस नेटवर्क वापस आने का पता लगाते हैं, तो वे सभी एक ही समय में रिट्राइ शुरू कर सकते हैं, जिससे सर्वर पर दबाव बढ़ सकता है। एक्सपोनेंशियल बैकऑफ़ प्रत्येक रिट्राइ को पिछले वाले की तुलना में अधिक समय तक प्रतीक्षा करने के लिए मजबूर करता है, जबकि जिटर एक रैंडम छोटा ऑफसेट जोड़ता है। यह संयोजन रिट्राइ ट्रैफिक को कुछ सेकंड में फैला देता है, जिससे अचानक आने वाले उछाल (spike) को रोका जा सकता है।

7. लेयर्ड (layered), सुलभ फीडबैक दिखाएं

एक तीन-स्तरीय स्टेटस बार फ़ाइल की वास्तविक स्थिति बताता है:

  • Received – सर्वर ने प्रत्येक चंक को स्टोर कर लिया है और फ़ाइल को पूरा (complete) मार्क कर दिया है।
  • Preparing – सर्वर थंबनेल जेनरेट कर रहा है या वीडियो को ट्रांसकोड (transcoding) कर रहा है।
  • Available – आयोजक फ़ाइल देख सकता है या डाउनलोड कर सकता है।

केवल रंग पर निर्भर रहने से बचें; आइकन के साथ संक्षिप्त टेक्स्ट का उपयोग करें ताकि स्क्रीन-रीडर उपयोगकर्ता भी प्रगति को समझ सकें।

क्या अभी भी कुछ गलत हो सकता है?

एक अच्छी तरह से इंजीनियर किया गया resumable upload भी कुछ edge cases में विफल हो सकता है।

आगे क्या ध्यान रखें

वेब प्लेटफॉर्म विकसित हो रहा है।

निष्कर्ष

एक resumable, chunked upload जो प्रत्येक हिस्से को ट्रैक करता है, state को स्थानीय रूप से स्टोर करता है, और बुद्धिमानी से retry करता है, एक अस्थिर इवेंट नेटवर्क को मेहमानों की तस्वीरों के लिए एक भरोसेमंद माध्यम में बदल देता है। ऊपर दी गई चेकलिस्ट को लागू करें।