'विंडो' पर 'btoa' निष्पादित करने में विफल: एन्कोडेड होने वाले स्ट्रिंग में लैटिन 1 श्रेणी के बाहर के वर्ण होते हैं।


133

मेरे परीक्षणों के अनुसार शीर्षक में त्रुटि केवल Google Chrome में डाली गई है। मैं एक बड़ी XML फ़ाइल को बेस 64 एन्कोडिंग कर रहा हूँ ताकि इसे डाउनलोड किया जा सके:

this.loader.src = "data:application/x-forcedownload;base64,"+
                  btoa("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                  +"<"+this.gamesave.tagName+">"
                  +this.xml.firstChild.innerHTML
                  +"</"+this.gamesave.tagName+">");

this.loader छिपा हुआ है iframe।

यह त्रुटि वास्तव में काफी परिवर्तन है क्योंकि आमतौर पर, Google Chrome btoaकॉल पर क्रैश हो जाएगा । मोज़िला फ़ायरफ़ॉक्स को यहाँ कोई समस्या नहीं है, इसलिए मुद्दा ब्राउज़र से संबंधित है। मुझे फ़ाइल में किसी भी अजीब अक्षर के बारे में पता नहीं है। वास्तव में मेरा मानना ​​है कि गैर-अस्सी के पात्र नहीं हैं।

प्रश्न: मैं समस्याग्रस्त पात्रों को कैसे खोजूं और उन्हें बदल दूं ताकि Chrome शिकायत करना बंद कर दे?

मैंने डाउनलोड आरंभ करने के लिए Downloadify का उपयोग करने की कोशिश की है, लेकिन यह काम नहीं करता है। यह अविश्वसनीय है और डिबग की अनुमति देने के लिए कोई त्रुटि नहीं है।

जवाबों:


213

यदि आपके पास UTF8 है, तो इसका उपयोग करें (वास्तव में SVG स्रोत के साथ काम करता है), जैसे:

btoa(unescape(encodeURIComponent(str)))

उदाहरण:

 var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(markup)));
 var img = new Image(1, 1); // width, height values are optional params 
 img.src = imgsrc;

यदि आपको उस बेस 64 को डीकोड करने की आवश्यकता है, तो इसका उपयोग करें:

var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);

उदाहरण:

var str = "äöüÄÖÜçéèñ";
var b64 = window.btoa(unescape(encodeURIComponent(str)))
console.log(b64);

var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);

नोट: यदि आपको मोबाइल-सफारी में काम करने के लिए यह प्राप्त करने की आवश्यकता है, तो आपको आधारभूत सुविधाओं से सभी श्वेत-स्थान को हटाने की आवश्यकता हो सकती है ...

function b64_to_utf8( str ) {
    str = str.replace(/\s/g, '');    
    return decodeURIComponent(escape(window.atob( str )));
}

2017 अपडेट

यह समस्या मुझे फिर से परेशान कर रही है।
सरल सत्य यह है कि, वास्तव में UTF8-strings को हैंडल नहीं करता है - यह केवल ASCII है।
इसके अलावा, मैं js-base64 जैसे ब्लोटवेयर का उपयोग नहीं करूंगा।
लेकिन वेबटॉकिट के पास एक छोटा, अच्छा और बहुत ही बेहतर कार्यान्वयन है:

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info
*
**/
var Base64 = {

    // private property
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

    // public method for encoding
    , encode: function (input)
    {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length)
        {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2))
            {
                enc3 = enc4 = 64;
            }
            else if (isNaN(chr3))
            {
                enc4 = 64;
            }

            output = output +
                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
        } // Whend 

        return output;
    } // End Function encode 


    // public method for decoding
    ,decode: function (input)
    {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (i < input.length)
        {
            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64)
            {
                output = output + String.fromCharCode(chr2);
            }

            if (enc4 != 64)
            {
                output = output + String.fromCharCode(chr3);
            }

        } // Whend 

        output = Base64._utf8_decode(output);

        return output;
    } // End Function decode 


    // private method for UTF-8 encoding
    ,_utf8_encode: function (string)
    {
        var utftext = "";
        string = string.replace(/\r\n/g, "\n");

        for (var n = 0; n < string.length; n++)
        {
            var c = string.charCodeAt(n);

            if (c < 128)
            {
                utftext += String.fromCharCode(c);
            }
            else if ((c > 127) && (c < 2048))
            {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else
            {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        } // Next n 

        return utftext;
    } // End Function _utf8_encode 

    // private method for UTF-8 decoding
    ,_utf8_decode: function (utftext)
    {
        var string = "";
        var i = 0;
        var c, c1, c2, c3;
        c = c1 = c2 = 0;

        while (i < utftext.length)
        {
            c = utftext.charCodeAt(i);

            if (c < 128)
            {
                string += String.fromCharCode(c);
                i++;
            }
            else if ((c > 191) && (c < 224))
            {
                c2 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else
            {
                c2 = utftext.charCodeAt(i + 1);
                c3 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }

        } // Whend 

        return string;
    } // End Function _utf8_decode 

}

https://www.fileformat.info/info/unicode/utf8.htm

  • 127 (हेक्स 0x7F) के बराबर या उससे नीचे के किसी भी वर्ण के लिए, UTF-8 प्रतिनिधित्व एक बाइट है। यह पूर्ण यूनिकोड मान के सबसे कम 7 बिट्स है। यह ASCII मान के समान ही है।

  • 2047 या उससे कम (हेक्स 0x07FF) के बराबर वर्णों के लिए, UTF-8 प्रतिनिधित्व दो बाइट्स में फैला हुआ है। पहले बाइट में दो हाई बिट्स सेट होंगे और तीसरा बिट क्लियर होगा (यानी 0xC2 से 0xDF)। दूसरी बाइट में टॉप बिट सेट और दूसरा बिट क्लियर होगा (यानी 0x80 से 0xBF)।

  • 2048 के बराबर या उससे अधिक के सभी वर्णों के लिए लेकिन 65535 (0xFFFF) से कम, UTF-8 का प्रतिनिधित्व तीन बाइट्स में फैला हुआ है।


6
क्या आप इसे थोड़ा और बढ़ा सकते हैं ... im पूरी तरह से खो दिया है
मुहम्मद उमर

अगर मैं तुम होता तो मैं सिर्फ कोड चलाता। escapeउस स्ट्रिंग को धर्मान्तरित करता है जिसमें केवल url मान्य वर्ण होते हैं। जो त्रुटियों को रोकता है।
टॉम ज़ातो -

6
escapeऔर unescapeजावास्क्रिप्ट 1.5 में पदावनत किया गया था और एक को इसके बजाय, क्रमशः encodeURIComponentया का उपयोग करना चाहिए decodeURIComponent। आप एक साथ पदावनत और नए कार्यों का उपयोग कर रहे हैं। क्यों? देखें: w3schools.com/jsref/jsref_escape.asp
Leif

2
@ लाइफ़: यह केवल सटीक रूप से काम करता है क्योंकि एस्केप और अनसेकैप छोटी गाड़ी (उसी तरह) हैं;)
स्टीफन स्टीगर

8
वेबपैक का उपयोग करने से किसी और को यहाँ घाव है?
अवींद्र गोलचरण

18

का उपयोग btoaकरना unescapeऔर encodeURIComponentमेरे लिए काम नहीं किया। XML / HTML संस्थाओं के साथ सभी विशेष वर्णों को प्रतिस्थापित करना और फिर base64 प्रतिनिधित्व में परिवर्तित करना मेरे लिए इस मुद्दे को हल करने का एकमात्र तरीका था। कुछ कोड:

base64 = btoa(str.replace(/[\u00A0-\u2666]/g, function(c) {
    return '&#' + c.charCodeAt(0) + ';';
}));

1
चूँकि मैंने यह प्रश्न पोस्ट किया था इसलिए मुझे एपीआई के बारे में कुछ पता चला जो कि मैं जो कर रहा था उसके लिए समर्पित हूं। यदि आप जिस स्ट्रिंग को परिवर्तित कर रहे हैं वह लंबी है, Blobतो रूपांतरण को संभालने के लिए ऑब्जेक्ट का उपयोग करें । Blobकिसी भी बाइनरी डेटा को संभाल सकते हैं।
टॉम ज़ातो -

1
IE9 के बारे में निश्चित नहीं है। लेकिन मेरा विचार यह है कि यदि आप बेस 64 रूपांतरण क्लाइंट-साइड जैसे सामान कर रहे हैं, तो आप शायद आधुनिक वेब-ऐप बना रहे हैं, जो कि जल्द या बाद में, आधुनिक सुविधाओं की आवश्यकता होगी। इसके अलावा, वहाँ एक बूँद polyfill है।
टॉम ज़ातो -

1
@ItaloBorssatto आप एक किंवदंती हैं!
कोडेपिक

1
@ItaloBorssatto यह एकमात्र समाधान था जिसने मेरे लिए काम किया। D3 svg चार्ट को हथियाने के लिए मुझे इसकी आवश्यकता थी, XMLSerializer का उपयोग करके इसे क्रमबद्ध करें, इसे btoa () में पास करें (यह वह जगह है जहां मैंने आपके समाधान का उपयोग किया है) एक बेस -64 एन्कोडेड ASCII स्ट्रिंग बनाने के लिए, फिर इसे इमेज एलिमेंट में पास करें फिर कैनवास में खींचा और फिर इसे निर्यात करें ताकि आप सामने के छोर पर एक छवि डाउनलोड कर सकें। बल्कि जटिल और हैक किए गए समाधान, लेकिन एक जिसे सर्वर-साइड रेंडर चार्ट की आवश्यकता नहीं होती है जब उपयोगकर्ता कुछ ग्राफिक्स डाउनलोड करना चाहते हैं। यदि आप रुचि रखते हैं तो मैं आपको कुछ कोड नमूने भेज सकता हूं। उनके लिए टिप्पणी बहुत छोटी है
कोडेपिक

1
@ItaloBorssatto <svg xmlns = " w3.org/2000/svg " viewBox = "0 0 1060 105" चौड़ाई = "1060" ऊँचाई = "105"> <पथ वर्ग = "डोमेन" स्ट्रोक = = कोई भी "d =" M -6,0.5H0.5V35.5H-6 "> <लाइन स्ट्रोक =" कोई नहीं "x2 =" - 6 "y1 =" 0.5 "y2 =" 0.5 "भरें =" कोई नहीं "स्ट्रोक-चौड़ाई =" 1px "फ़ॉन्ट- family = "sans-serif" font-size = "10px" /> <text fill = "rgb (196, 196, 196)" x = "- 9" y = "0.5" dy = "0.32em"> FogueEspana - Vogue España </ text> <rect class = "first bar" fill = "rgb (25, 244, 71)" x = "0" y = "8" चौड़ाई = "790" ऊँचाई = "18" /> </ g> </ svg> मैंने अप्रासंगिक टुकड़ों को काट दिया। अपराधी Vogue España -> है from ब्राउज़र में एक छवि को लोड होने से रोका गया।
कोडेपिक

15

इसके बजाय किसी लाइब्रेरी का उपयोग करें

हमें पहिए को फिर से नहीं लगाना है। समय और सिरदर्द को बचाने के लिए बस एक पुस्तकालय का उपयोग करें।

js-base64

https://github.com/dankogai/js-base64 अच्छा है और मैं इसकी पुष्टि करता हूं कि यह बहुत अच्छी तरह से यूनिकोड का समर्थन करता है।

Base64.encode('dankogai');  // ZGFua29nYWk=
Base64.encode('小飼弾');    // 5bCP6aO85by+
Base64.encodeURI('小飼弾'); // 5bCP6aO85by-

Base64.decode('ZGFua29nYWk=');  // dankogai
Base64.decode('5bCP6aO85by+');  // 小飼弾
// note .decodeURI() is unnecessary since it accepts both flavors
Base64.decode('5bCP6aO85by-');  // 小飼弾

यह एक अच्छा समाधान है, हालांकि यह बोसा के लिए ASCII तक सीमित होने के लिए एक निरीक्षण की तरह लगता है (हालांकि एटब डिकोडिंग ठीक काम करने लगता है)। अन्य उत्तरों में से कई के बाद यह मेरे लिए काम नहीं करेगा। धन्यवाद!
नाम

9

मुझे लगा कि मुझे यह साझा करना चाहिए कि मैंने वास्तव में समस्या को कैसे हल किया और मुझे लगता है कि यह अधिकार क्यों है समाधान है (बशर्ते आप पुराने ब्राउज़र के लिए अनुकूलन न करें)।

DataurL को डेटा परिवर्तित करना ( data: ...)

var blob = new Blob(
              // I'm using page innerHTML as data
              // note that you can use the array
              // to concatenate many long strings EFFICIENTLY
              [document.body.innerHTML],
              // Mime type is important for data url
              {type : 'text/html'}
); 
// This FileReader works asynchronously, so it doesn't lag
// the web application
var a = new FileReader();
a.onload = function(e) {
     // Capture result here
     console.log(e.target.result);
};
a.readAsDataURL(blob);

डेटा को बचाने के लिए उपयोगकर्ता को अनुमति देना

स्पष्ट समाधान के अलावा - URL के रूप में अपने dataURL के साथ नई विंडो खोलना आप दो अन्य चीजें कर सकते हैं।

1. उपयोग FileSaver.js का

फ़ाइल सेवर पूर्वनिर्धारित फ़ाइल नाम के साथ वास्तविक फ़ाइल सेव संवाद बना सकता है। यह सामान्य डेटाुरल एप्रोच में भी गिरावट कर सकता है।

2. प्रयोग (प्रयोगात्मक) URL.createObjectURL

यह बेस 64 एनकोडेड डेटा के पुन: उपयोग के लिए बहुत अच्छा है। यह आपके dataURL के लिए एक छोटा URL बनाता है:

console.log(URL.createObjectURL(blob));
//Prints: blob:http://stackoverflow.com/7c18953f-f5f8-41d2-abf5-e9cbced9bc42

अग्रणी blobउपसर्ग सहित URL का उपयोग करना न भूलें । मैंने document.bodyफिर से उपयोग किया :

चित्र का वर्णन

आप इस छोटे URL को AJAX लक्ष्य, <script>स्रोत या <a>href स्थान के रूप में उपयोग कर सकते हैं । यद्यपि आप URL को नष्ट करने के लिए जिम्मेदार हैं:

URL.revokeObjectURL('blob:http://stackoverflow.com/7c18953f-f5f8-41d2-abf5-e9cbced9bc42')

धन्यवाद दोस्त, आपने मेरा दिन बचा लिया :)
संदीप कुमार

3

स्टीफन स्टीगर के जवाब के पूरक के रूप में: (जैसा कि यह एक टिप्पणी के रूप में अच्छा नहीं लगता है)

स्ट्रिंग प्रोटोटाइप का विस्तार:

String.prototype.b64encode = function() { 
    return btoa(unescape(encodeURIComponent(this))); 
};
String.prototype.b64decode = function() { 
    return decodeURIComponent(escape(atob(this))); 
};

उपयोग:

var str = "äöüÄÖÜçéèñ";
var encoded = str.b64encode();
console.log( encoded.b64decode() );

ध्यान दें:

जैसा कि टिप्पणियों में कहा गया है, का उपयोग करने unescapeकी अनुशंसा नहीं की जाती है क्योंकि इसे भविष्य में हटाया जा सकता है:

चेतावनी : हालांकि unescape () को सख्ती से नहीं हटाया गया है (जैसा कि "वेब मानकों से हटा दिया गया है"), यह ECMA-262 मानक के अनुबंध बी में परिभाषित किया गया है, जिसका परिचय बताता है: ... भाषा की सभी विशेषताएं और व्यवहार इसमें निर्दिष्ट हैं एनेक्स में एक या अधिक अवांछनीय विशेषताएं हैं और विरासत के उपयोग के अभाव में इस विनिर्देश को हटा दिया जाएगा।

नोट: URIs को डिकोड करने के लिए unescape का उपयोग न करें, इसके बजाय decodeURI या decodeURIComponent का उपयोग करें।


6
कार्य अच्छे लगते हैं, लेकिन आधार प्रोटोटाइप का विस्तार करना एक बुरा अभ्यास है।
टाइममेकाइन 3030

4
जावास्क्रिप्ट एक बुरा अभ्यास है। एक और हैक क्या है, धन्यवाद।
रोब ५४०

1
@ rob5408: जबकि मैं सिद्धांत रूप में आपके कथन से सहमत हूं, लेकिन आपको वास्तव में अधिक सतर्क रहना चाहिए: प्रोटोटाइप को विस्तारित करने से jQuery (एक और पुस्तकालय जो "सिर्फ एक और हैक" सिद्धांत का उपयोग करता है)
स्टीफन स्टीगर

@StefanSteiger पता करने के लिए अच्छा है, अंतर्दृष्टि के लिए धन्यवाद।
195 बजे रोब 5408


2

btoa () केवल String.fromCodePoint (0) से String.fromCodePoint (255) तक वर्णों का समर्थन करते हैं। एक कोड बिंदु 256 या उच्चतर के साथ Base64 वर्णों के लिए आपको इनको पहले और बाद में इनकोड / डिकोड करना होगा।

और इस बिंदु में यह मुश्किल हो जाता है ...

हर संभव संकेत एक यूनिकोड-टेबल में व्यवस्थित हैं। यूनिकोड-तालिका को विभिन्न विमानों (भाषाओं, गणित के प्रतीकों, और इसी तरह ...) में विभाजित किया गया है। एक प्लेन के हर चिन्ह में एक यूनिक कोड पॉइंट नंबर होता है। सैद्धांतिक रूप से, संख्या मनमाने ढंग से बड़ी हो सकती है।

एक कंप्यूटर बाइट्स में डेटा संग्रहीत करता है (8 बिट, हेक्साडेसिमल 0x00 - 0xff, बाइनरी 00000000 - 11111111, दशमलव 0 - 255)। यह सीमा आम तौर पर बुनियादी पात्रों (लैटिन 1 रेंज) को बचाने के लिए उपयोग की जाती है।

उच्च कोडपॉइंट वाले वर्णों के लिए 255 अलग-अलग एनकोडिंग होते हैं। जावास्क्रिप्ट प्रति चिह्न (UTF-16), DOMString नामक स्ट्रिंग का उपयोग करते हैं। यूनिकोड 0x10fffff तक के कोड पॉइंट्स को हैंडल कर सकता है। इसका मतलब है, कि एक विधि कई कोशिकाओं को दूर कई बिट्स को स्टोर करने के लिए मौजूद होना चाहिए।

String.fromCodePoint(0x10000).length == 2

UTF-16 दो 16bit कोशिकाओं में 20bit स्टोर करने के लिए सरोगेट जोड़े का उपयोग करता है। पहले उच्च सरोगेट की शुरुआत 110110xxxxxxxxxx के साथ , दूसरे में 110111xxxxxxxxxx के साथ होती है । इसके लिए यूनिकोड ने स्वयं के विमान आरक्षित किए: https://unicode-table.com/de/#high-surrogates

वर्णों को बाइट्स (लैटिन 1 श्रेणी) में संग्रहीत करने के लिए मानकीकृत प्रक्रियाएँ यूटीएफ -8 का उपयोग करती हैं ।

यह कहने के लिए क्षमा करें, लेकिन मुझे लगता है कि इस फ़ंक्शन को स्वयं लागू करने का कोई अन्य तरीका नहीं है।

function stringToUTF8(str)
{
    let bytes = [];

    for(let character of str)
    {
        let code = character.codePointAt(0);

        if(code <= 127)
        {
            let byte1 = code;

            bytes.push(byte1);
        }
        else if(code <= 2047)
        {
            let byte1 = 0xC0 | (code >> 6);
            let byte2 = 0x80 | (code & 0x3F);

            bytes.push(byte1, byte2);
        }
        else if(code <= 65535)
        {
            let byte1 = 0xE0 | (code >> 12);
            let byte2 = 0x80 | ((code >> 6) & 0x3F);
            let byte3 = 0x80 | (code & 0x3F);

            bytes.push(byte1, byte2, byte3);
        }
        else if(code <= 2097151)
        {
            let byte1 = 0xF0 | (code >> 18);
            let byte2 = 0x80 | ((code >> 12) & 0x3F);
            let byte3 = 0x80 | ((code >> 6) & 0x3F);
            let byte4 = 0x80 | (code & 0x3F);

            bytes.push(byte1, byte2, byte3, byte4);
        }
    }

    return bytes;
}

function utf8ToString(bytes, fallback)
{
    let valid = undefined;
    let codePoint = undefined;
    let codeBlocks = [0, 0, 0, 0];

    let result = "";

    for(let offset = 0; offset < bytes.length; offset++)
    {
        let byte = bytes[offset];

        if((byte & 0x80) == 0x00)
        {
            codeBlocks[0] = byte & 0x7F;

            codePoint = codeBlocks[0];
        }
        else if((byte & 0xE0) == 0xC0)
        {
            codeBlocks[0] = byte & 0x1F;

            byte = bytes[++offset];
            if(offset >= bytes.length || (byte & 0xC0) != 0x80) { valid = false; break; }

            codeBlocks[1] = byte & 0x3F;

            codePoint = (codeBlocks[0] << 6) + codeBlocks[1];
        }
        else if((byte & 0xF0) == 0xE0)
        {
            codeBlocks[0] = byte & 0xF;

            for(let blockIndex = 1; blockIndex <= 2; blockIndex++)
            {
                byte = bytes[++offset];
                if(offset >= bytes.length || (byte & 0xC0) != 0x80) { valid = false; break; }

                codeBlocks[blockIndex] = byte & 0x3F;
            }
            if(valid === false) { break; }

            codePoint = (codeBlocks[0] << 12) + (codeBlocks[1] << 6) + codeBlocks[2];
        }
        else if((byte & 0xF8) == 0xF0)
        {
            codeBlocks[0] = byte & 0x7;

            for(let blockIndex = 1; blockIndex <= 3; blockIndex++)
            {
                byte = bytes[++offset];
                if(offset >= bytes.length || (byte & 0xC0) != 0x80) { valid = false; break; }

                codeBlocks[blockIndex] = byte & 0x3F;
            }
            if(valid === false) { break; }

            codePoint = (codeBlocks[0] << 18) + (codeBlocks[1] << 12) + (codeBlocks[2] << 6) + (codeBlocks[3]);
        }
        else
        {
            valid = false; break;
        }

        result += String.fromCodePoint(codePoint);
    }

    if(valid === false)
    {
        if(!fallback)
        {
            throw new TypeError("Malformed utf-8 encoding.");
        }

        result = "";

        for(let offset = 0; offset != bytes.length; offset++)
        {
            result += String.fromCharCode(bytes[offset] & 0xFF);
        }
    }

    return result;
}

function decodeBase64(text, binary)
{
    if(/[^0-9a-zA-Z\+\/\=]/.test(text)) { throw new TypeError("The string to be decoded contains characters outside of the valid base64 range."); }

    let codePointA = 'A'.codePointAt(0);
    let codePointZ = 'Z'.codePointAt(0);
    let codePointa = 'a'.codePointAt(0);
    let codePointz = 'z'.codePointAt(0);
    let codePointZero = '0'.codePointAt(0);
    let codePointNine = '9'.codePointAt(0);
    let codePointPlus = '+'.codePointAt(0);
    let codePointSlash = '/'.codePointAt(0);

    function getCodeFromKey(key)
    {
        let keyCode = key.codePointAt(0);

        if(keyCode >= codePointA && keyCode <= codePointZ)
        {
            return keyCode - codePointA;
        }
        else if(keyCode >= codePointa && keyCode <= codePointz)
        {
            return keyCode + 26 - codePointa;
        }
        else if(keyCode >= codePointZero && keyCode <= codePointNine)
        {
            return keyCode + 52 - codePointZero;
        }
        else if(keyCode == codePointPlus)
        {
            return 62;
        }
        else if(keyCode == codePointSlash)
        {
            return 63;
        }

        return undefined;
    }

    let codes = Array.from(text).map(character => getCodeFromKey(character));

    let bytesLength = Math.ceil(codes.length / 4) * 3;

    if(codes[codes.length - 2] == undefined) { bytesLength = bytesLength - 2; } else if(codes[codes.length - 1] == undefined) { bytesLength--; }

    let bytes = new Uint8Array(bytesLength);

    for(let offset = 0, index = 0; offset < bytes.length;)
    {
        let code1 = codes[index++];
        let code2 = codes[index++];
        let code3 = codes[index++];
        let code4 = codes[index++];

        let byte1 = (code1 << 2) | (code2 >> 4);
        let byte2 = ((code2 & 0xf) << 4) | (code3 >> 2);
        let byte3 = ((code3 & 0x3) << 6) | code4;

        bytes[offset++] = byte1;
        bytes[offset++] = byte2;
        bytes[offset++] = byte3;
    }

    if(binary) { return bytes; }

    return utf8ToString(bytes, true);
}

function encodeBase64(bytes) {
    if (bytes === undefined || bytes === null) {
        return '';
    }
    if (bytes instanceof Array) {
        bytes = bytes.filter(item => {
            return Number.isFinite(item) && item >= 0 && item <= 255;
        });
    }

    if (
        !(
            bytes instanceof Uint8Array ||
            bytes instanceof Uint8ClampedArray ||
            bytes instanceof Array
        )
    ) {
        if (typeof bytes === 'string') {
            const str = bytes;
            bytes = Array.from(unescape(encodeURIComponent(str))).map(ch =>
                ch.codePointAt(0)
            );
        } else {
            throw new TypeError('bytes must be of type Uint8Array or String.');
        }
    }

    const keys = [
        'A',
        'B',
        'C',
        'D',
        'E',
        'F',
        'G',
        'H',
        'I',
        'J',
        'K',
        'L',
        'M',
        'N',
        'O',
        'P',
        'Q',
        'R',
        'S',
        'T',
        'U',
        'V',
        'W',
        'X',
        'Y',
        'Z',
        'a',
        'b',
        'c',
        'd',
        'e',
        'f',
        'g',
        'h',
        'i',
        'j',
        'k',
        'l',
        'm',
        'n',
        'o',
        'p',
        'q',
        'r',
        's',
        't',
        'u',
        'v',
        'w',
        'x',
        'y',
        'z',
        '0',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
        '+',
        '/'
    ];
    const fillKey = '=';

    let byte1;
    let byte2;
    let byte3;
    let sign1 = ' ';
    let sign2 = ' ';
    let sign3 = ' ';
    let sign4 = ' ';

    let result = '';

    for (let index = 0; index < bytes.length; ) {
        let fillUpAt = 0;

        // tslint:disable:no-increment-decrement
        byte1 = bytes[index++];
        byte2 = bytes[index++];
        byte3 = bytes[index++];

        if (byte2 === undefined) {
            byte2 = 0;
            fillUpAt = 2;
        }

        if (byte3 === undefined) {
            byte3 = 0;
            if (!fillUpAt) {
                fillUpAt = 3;
            }
        }

        // tslint:disable:no-bitwise
        sign1 = keys[byte1 >> 2];
        sign2 = keys[((byte1 & 0x3) << 4) + (byte2 >> 4)];
        sign3 = keys[((byte2 & 0xf) << 2) + (byte3 >> 6)];
        sign4 = keys[byte3 & 0x3f];

        if (fillUpAt > 0) {
            if (fillUpAt <= 2) {
                sign3 = fillKey;
            }
            if (fillUpAt <= 3) {
                sign4 = fillKey;
            }
        }

        result += sign1 + sign2 + sign3 + sign4;

        if (fillUpAt) {
            break;
        }
    }

    return result;
}

let base64 = encodeBase64("\u{1F604}"); // unicode code point escapes for smiley
let str = decodeBase64(base64);

console.log("base64", base64);
console.log("str", str);

document.body.innerText = str;

इसे कैसे उपयोग करे: decodeBase64(encodeBase64("\u{1F604}"))

डेमो: https://jsfiddle.net/qrLadeb8/


बहुत अच्छा काम करता है! 🎉 मैं नहीं दिख रहा है जहां आप की जरूरत stringToUTF8है और utf8ToStringयद्यपि
बेंजामिन Toueg

1

मैं खुद इस समस्या में भाग गया।

सबसे पहले, अपने कोड को थोड़ा संशोधित करें:

var download = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                  +"<"+this.gamesave.tagName+">"
                  +this.xml.firstChild.innerHTML
                  +"</"+this.gamesave.tagName+">";

this.loader.src = "data:application/x-forcedownload;base64,"+
                  btoa(download);

फिर अपने पसंदीदा वेब इंस्पेक्टर का उपयोग करें, उस कोड की लाइन पर एक ब्रेकपॉइंट लगाएं जो इस .loader.src को असाइन करता है, फिर इस कोड को निष्पादित करें:

for (var i = 0; i < download.length; i++) {
  if (download[i].charCodeAt(0) > 255) {
    console.warn('found character ' + download[i].charCodeAt(0) + ' "' + download[i] + '" at position ' + i);
  }
}

आपके आवेदन के आधार पर, वर्णों को बदलना जो सीमा से बाहर हैं या काम नहीं कर सकते हैं, क्योंकि आप डेटा को संशोधित कर रहे हैं। एमडीएन पर नोट को यूनिकोड वर्णों के बारे में बोटो विधि से देखें:

https://developer.mozilla.org/en-US/docs/Web/API/window.btoa

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.