क्यों atob() बाइट्स लौटाता है और btoa() कुछ टेक्स्ट को अस्वीकार करता है

JavaScript बाइनरी स्ट्रिंग्स, कैरेक्टर-रेंज त्रुटियों और atob और btoa के लिए आवश्यक UTF-8 चरण को समझें।

नाम atob और btoa साधारण पाठ रूपांतरण का सुझाव दे सकता है। उनका ब्राउज़र अनुबंध संकीर्ण है: वे Base64 टेक्स्ट और एक स्ट्रिंग के बीच परिवर्तित होते हैं जिनके वर्ण मान व्यक्तिगत बाइट्स का प्रतिनिधित्व करते हैं। वह बाइट स्ट्रिंग एक कंटेनर है, यह वादा नहीं है कि परिणाम पढ़ने योग्य यूनिकोड टेक्स्ट है।

दो अलग-अलग तार

JavaScript स्ट्रिंग्स UTF-16 कोड इकाइयों का उपयोग करती हैं। एक बाइट स्ट्रिंग जानबूझकर प्रत्येक वर्ण मान को 0-255 तक सीमित करती है। btoa('Hello') काम करता है क्योंकि ASCII मान उस सीमा में फिट होते हैं। btoa('你好') विफल हो जाता है क्योंकि वे अक्षर एक बाइट में फ़िट नहीं होते हैं। यहां तक कि जो पात्र फिट बैठता है वह भी भ्रामक हो सकता है: btoa('é') एकल बाइट E9 को एन्कोड करता है, न कि कई सेवाओं द्वारा अपेक्षित UTF-8 बाइट्स C3 A9 को।

console.log(btoa('é')); // 6Q== (byte E9)
console.log(btoa(String.fromCharCode(0xc3, 0xa9))); // w6k= (UTF-8)

बाइट फ़ंक्शंस के आसपास UTF-8 रूपांतरण रखें

TextEncoder पाठ से UTF-8 बाइट्स उत्पन्न करता है। Base64 को डिकोड करने के बाद, एक घातक TextDecoder वैध UTF-8 बाइट्स को वापस टेक्स्ट में परिवर्तित करता है और अमान्य अनुक्रमों को चुपचाप बदलने के बजाय अस्वीकार कर देता है। यह छोटा सा उदाहरण जानबूझकर स्पष्ट है ताकि सीमा दिखाई दे।

const text = '中文😊';
const bytes = new TextEncoder().encode(text);
let binary = '';
for (const byte of bytes) binary += String.fromCharCode(byte);
const encoded = btoa(binary);
console.log(encoded); // 5Lit5paH8J+Yig==
const decodedBytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const decoded = new TextDecoder('utf-8', { fatal: true }).decode(decodedBytes);
console.log(decoded); // 中文😊

किसी बाइनरी परिणाम को टूटी हुई स्ट्रिंग के रूप में न मानें

atob('/w==') बाइट एफएफ का प्रतिनिधित्व करता है। यह अपने आप में वैध UTF-8 नहीं है, लेकिन यह पूरी तरह से वैध बाइनरी डेटा है। सही अगली क्रिया बाइट डाउनलोड या हेक्साडेसिमल दृश्य हो सकती है, कोई भिन्न टेक्स्ट रूपांतरण ट्रिक नहीं। उस बाइट स्ट्रिंग को चलाएँ TextEncoder वर्ण U+00FF को एन्कोड करेगा और बाइट्स बदल देगा।

ब्राउज़र डिकोडर भी पूर्ण प्रोटोकॉल सत्यापनकर्ता नहीं है। स्वीकृत रिक्त स्थान और छोड़ी गई पैडिंग सख्त आवेदन आवश्यकताओं से भिन्न हो सकती है। यदि किसी प्रोटोकॉल के लिए कैनोनिकल एन्कोडिंग की आवश्यकता होती है, तो वर्णमाला, पैडिंग और अप्रयुक्त बिट्स को अलग से मान्य करें। बड़ी फ़ाइलों के लिए, संपूर्ण बाइट सरणी को फैलाने से बचें String.fromCharCode(...bytes); फ़ाइल के असामान्य रूप से बड़े होने से बहुत पहले ही तर्क-गणना सीमाएँ विफल हो सकती हैं।

ब्राउज़र अनुबंध पढ़ें एमडीएन: एटोब() और एमडीएन: btoa(). एप्लिकेशन को यह तय करना चाहिए कि क्या वह एक अनुमेय रूपांतरण, एक सख्त सत्यापनकर्ता या फ़ाइल-संरक्षित वर्कफ़्लो चाहता है, बजाय यह मानने के कि ये वही कार्य हैं।