Base64 को डिकोड करने के लिए जावास्क्रिप्ट एटब का उपयोग करना utf-8 स्ट्रिंग्स को ठीक से डिकोड नहीं करता है


106

मैं window.atob()बेस -64-एन्कोडेड स्ट्रिंग (विशेष रूप से GitHub API से बेस 64-एन्कोडेड सामग्री) को डीकोड करने के लिए जावास्क्रिप्ट फ़ंक्शन का उपयोग कर रहा हूं । समस्या यह है कि मुझे ASCII-एन्कोड किए गए वर्ण वापस मिल रहे हैं (जैसे के â¢बजाय )। मैं आने वाली बेस 64-एनकोडेड स्ट्रीम को कैसे ठीक से संभाल सकता हूं ताकि यह utf-8 के रूप में डिकोड हो जाए?


3
आपके द्वारा लिंक किया गया MDN पृष्ठ "यूनिकोड या UTF-8 स्ट्रिंग्स के साथ उपयोग के लिए" वाक्यांश के साथ शुरू होने वाला एक पैराग्राफ है।
नुकीले

1
क्या आप नोड पर हैं? इससे बेहतर उपाय हैंatob
बरगी

जवाबों:


269

मोज़िला के MDN डॉक्स पर एक बेहतरीन लेख है जो इस मुद्दे का सटीक वर्णन करता है:

"यूनिकोड प्रॉब्लम" चूंकि DOMStrings 16-बिट-एन्कोडेड स्ट्रिंग्स है, इसलिए अधिकांश window.btoaयूनिकोड स्ट्रिंग पर कॉल करने पर Character Out Of Range exceptionएक कैरेक्टर 8-बिट बाइट (0x00 ~ 0xFF) की सीमा से अधिक हो जाएगा। इस समस्या को हल करने के दो संभावित तरीके हैं:

  • पहले एक पूरे स्ट्रिंग से बचने के लिए है (UTF-8 के साथ, देखें encodeURIComponent) और फिर इसे एनकोड करें;
  • दूसरा एक UTF-16 DOMStringको UTF-8 वर्णों में बदलना है और फिर उसे एनकोड करना है।

पिछले समाधानों पर एक नोट: एमडीएन लेख मूल रूप से अपवाद समस्या का उपयोग करने unescapeऔर escapeहल करने का सुझाव दिया गया Character Out Of Rangeथा, लेकिन उन्हें तब से हटा दिया गया है। यहाँ कुछ अन्य उत्तरों ने इसके साथ काम करने का सुझाव दिया है decodeURIComponentऔर encodeURIComponent, यह अविश्वसनीय और अप्रत्याशित साबित हुआ है। इस उत्तर के लिए सबसे हालिया अपडेट आधुनिक जावास्क्रिप्ट कार्यों का उपयोग गति में सुधार और कोड को आधुनिक बनाने के लिए करता है।

यदि आप कुछ समय के लिए खुद को बचाने की कोशिश कर रहे हैं, तो आप एक पुस्तकालय का उपयोग करने पर भी विचार कर सकते हैं:

UTF8 64 बेस 64 एनकोडिंग

function b64EncodeUnicode(str) {
    // first we use encodeURIComponent to get percent-encoded UTF-8,
    // then we convert the percent encodings into raw bytes which
    // can be fed into btoa.
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function toSolidBytes(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n'); // "Cg=="

डिकोडिंग बेस 64 base UTF8

function b64DecodeUnicode(str) {
    // Going backwards: from bytestream, to percent-encoding, to original string.
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
b64DecodeUnicode('Cg=='); // "\n"

2018 से पहले का समाधान (कार्यात्मक, और संभवतः पुराने ब्राउज़र के लिए बेहतर समर्थन, आज तक नहीं)

यहाँ वर्तमान अनुशंसा, MDN से प्रत्यक्ष है, @ MA-Maddin के माध्यम से कुछ अतिरिक्त टाइपस्क्रिप्ट संगतता के साथ:

// Encoding UTF8 ⇢ base64

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode(parseInt(p1, 16))
    }))
}

b64EncodeUnicode('✓ à la mode') // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n') // "Cg=="

// Decoding base64 ⇢ UTF8

function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    }).join(''))
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=') // "✓ à la mode"
b64DecodeUnicode('Cg==') // "\n"

मूल समाधान (पदावनत)

यह प्रयोग किया जाता है escapeऔर unescape(जो अब हटाए गए हैं, हालांकि यह अभी भी सभी आधुनिक ब्राउज़रों में काम करता है):

function utf8_to_b64( str ) {
    return window.btoa(unescape(encodeURIComponent( str )));
}

function b64_to_utf8( str ) {
    return decodeURIComponent(escape(window.atob( str )));
}

// Usage:
utf8_to_b64('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64_to_utf8('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

और एक आखिरी बात: मुझे पहली बार GitHub API को कॉल करते समय इस समस्या का सामना करना पड़ा। इसे (मोबाइल) सफारी पर ठीक से काम करने के लिए, मुझे वास्तव में बेस 64 स्रोत से सभी सफेद स्थान को छीनना पड़ा, इससे पहले कि मैं स्रोत को डिकोड कर सकता। 2017 में यह अभी भी प्रासंगिक है या नहीं, मुझे नहीं पता:

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

1
w3schools.com/jsref/jsref_unescape.asp "unescape () फ़ंक्शन JavaScript संस्करण 1.5 में पदावनत किया गया था। इसके बजाय decodeURI () या decodeURIComponent () का उपयोग करें।"
टेड हैन्सन

1
आपने मेरे दिनों को बचाया, भाई
श्री नव

2
अपडेट: एमडीएन की "यूनिकोड समस्या" में समाधान # 1 तय किया गया था, b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=');अब सही ढंग से "la à la mode" आउटपुट
weeix

2
डिकोड करने का दूसरा तरीका decodeURIComponent(atob('4pyTIMOgIGxhIG1vZGU=').split('').map(x => '%' + x.charCodeAt(0).toString(16)).join('')) न केवल सबसे अच्छा प्रदर्शन कोड होगा, बल्कि यह वही है जो यह है।
daniel.gindi

2
return String.fromCharCode(parseInt(p1, 16));टाइपस्क्रिप्ट संगतता है।
मार्टिन श्नाइडर

20

चीज़ें बदल जाती हैं। भागने / unescape तरीकों पदावनत किया गया है।

आप बेस 64-एनकोड करने से पहले यूआरआई स्ट्रिंग को एनकोड कर सकते हैं। ध्यान दें कि यह Base64- एन्कोडेड UTF8 का उत्पादन नहीं कर सकता है, बल्कि Base64- एन्कोडेड URL-एन्कोडेड डेटा है। दोनों पक्षों को एक ही एन्कोडिंग पर सहमत होना चाहिए।

कार्यशील उदाहरण यहां देखें: http://codepen.io/anon/pen/PZgbPW

// encode string
var base64 = window.btoa(encodeURIComponent('€ 你好 æøåÆØÅ'));
// decode string
var str = decodeURIComponent(window.atob(tmp));
// str is now === '€ 你好 æøåÆØÅ'

ओपी की समस्या के लिए js-base64 जैसे तीसरे पक्ष के पुस्तकालय को समस्या को हल करना चाहिए।


1
मैं इंगित करना चाहता हूं कि आप इनपुट स्ट्रिंग के बेस 64 का निर्माण नहीं कर रहे हैं, लेकिन उसके एन्कोडेड घटक का। इसलिए यदि आप इसे भेज देते हैं तो दूसरी पार्टी इसे "बेस 64" के रूप में डिकोड नहीं कर सकती है और मूल स्ट्रिंग प्राप्त कर सकती है
रिकार्डो गली

3
आप सही हैं, मैंने उस बिंदु को इंगित करने के लिए पाठ को अपडेट किया है। धन्यवाद। वैकल्पिक रूप से बेस पार्टी को लागू करना प्रतीत होता है, तीसरे पक्ष के पुस्तकालय (जैसे js-base64) का उपयोग करके या "त्रुटि: प्राप्त करने में विफल '' विंडो 'पर' बटाओ 'को निष्पादित करने में विफल: एन्कोड किए जाने वाले स्ट्रिंग में लैटिन श्रेणी के बाहर वर्ण होते हैं। "
टेड हेन्सन

14

यदि बाइट्स के रूप में स्ट्रिंग्स का इलाज करना आपकी चीज है, तो आप निम्नलिखित कार्यों का उपयोग कर सकते हैं

function u_atob(ascii) {
    return Uint8Array.from(atob(ascii), c => c.charCodeAt(0));
}

function u_btoa(buffer) {
    var binary = [];
    var bytes = new Uint8Array(buffer);
    for (var i = 0, il = bytes.byteLength; i < il; i++) {
        binary.push(String.fromCharCode(bytes[i]));
    }
    return btoa(binary.join(''));
}


// example, it works also with astral plane characters such as '𝒞'
var encodedString = new TextEncoder().encode('✓');
var base64String = u_btoa(encodedString);
console.log('✓' === new TextDecoder().decode(u_atob(base64String)))

1
धन्यवाद। आपका जवाब मुझे इस काम को पाने में मदद करने में महत्वपूर्ण था, जिसने मुझे कई दिनों तक कई घंटे लगाये। +1। stackoverflow.com/a/51814273/470749
रयान

बहुत तेज़ और अधिक क्रॉस-ब्राउज़र समाधान (लेकिन अनिवार्य रूप से समान आउटपुट) के लिए, कृपया देखें stackoverflow.com/a/53433503/5601591
जैक गिफिन

u_atob और u_btoa IE10 (2012) के बाद से हर ब्राउज़र में उपलब्ध फ़ंक्शंस का उपयोग करते हैं, मुझे ठोस लगता है (यदि आप TextEncoder का उल्लेख करते हैं, तो यह सिर्फ एक उदाहरण है)
रिकार्डो गली

5

यहां मोजिला विकास संसाधन में वर्णित 2018 अद्यतन समाधान है

B64 को UNICODE से संलग्न करना

function b64EncodeUnicode(str) {
    // first we use encodeURIComponent to get percent-encoded UTF-8,
    // then we convert the percent encodings into raw bytes which
    // can be fed into btoa.
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function toSolidBytes(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n'); // "Cg=="

B64 से यूनिकोड के लिए आदेश जारी करना

function b64DecodeUnicode(str) {
    // Going backwards: from bytestream, to percent-encoding, to original string.
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
b64DecodeUnicode('Cg=='); // "\n"

4

पूरा लेख जो मेरे लिए काम करता है: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding

वह हिस्सा जहां हम यूनिकोड / UTF-8 से एनकोड करते हैं

function utf8_to_b64( str ) {
   return window.btoa(unescape(encodeURIComponent( str )));
}

function b64_to_utf8( str ) {
   return decodeURIComponent(escape(window.atob( str )));
}

// Usage:
utf8_to_b64('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64_to_utf8('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

यह आजकल सबसे अधिक उपयोग की जाने वाली विधियों में से एक है।


स्वीकार किए गए उत्तर के समान ही लिंक है।
ब्रैंडनस्क्रिप्ट 14

3

मुझे लगता है कि एक समाधान है कि एक व्यापक रूप से प्रयोग करने योग्य base64 URI पैदा करता है चाहते हो सकता है। कृपया data:text/plain;charset=utf-8;base64,4pi44pi54pi64pi74pi84pi+4pi/एक प्रदर्शन देखने के लिए जाएं (डेटा uri की प्रतिलिपि बनाएँ, एक नया टैब खोलें, डेटा URI को पता बार में पेस्ट करें, फिर पृष्ठ पर जाने के लिए एंटर दबाएं)। इस तथ्य के बावजूद कि यह यूआरआई बेस 64-एनकोडेड है, ब्राउज़र अभी भी उच्च कोड बिंदुओं को पहचानने और उन्हें ठीक से डिकोड करने में सक्षम है। छोटा एनकोडर + डिकोडर 1058 बाइट्स (+ गज़िप → 589 बाइट्स) है

!function(e){"use strict";function h(b){var a=b.charCodeAt(0);if(55296<=a&&56319>=a)if(b=b.charCodeAt(1),b===b&&56320<=b&&57343>=b){if(a=1024*(a-55296)+b-56320+65536,65535<a)return d(240|a>>>18,128|a>>>12&63,128|a>>>6&63,128|a&63)}else return d(239,191,189);return 127>=a?inputString:2047>=a?d(192|a>>>6,128|a&63):d(224|a>>>12,128|a>>>6&63,128|a&63)}function k(b){var a=b.charCodeAt(0)<<24,f=l(~a),c=0,e=b.length,g="";if(5>f&&e>=f){a=a<<f>>>24+f;for(c=1;c<f;++c)a=a<<6|b.charCodeAt(c)&63;65535>=a?g+=d(a):1114111>=a?(a-=65536,g+=d((a>>10)+55296,(a&1023)+56320)):c=0}for(;c<e;++c)g+="\ufffd";return g}var m=Math.log,n=Math.LN2,l=Math.clz32||function(b){return 31-m(b>>>0)/n|0},d=String.fromCharCode,p=atob,q=btoa;e.btoaUTF8=function(b,a){return q((a?"\u00ef\u00bb\u00bf":"")+b.replace(/[\x80-\uD7ff\uDC00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g,h))};e.atobUTF8=function(b,a){a||"\u00ef\u00bb\u00bf"!==b.substring(0,3)||(b=b.substring(3));return p(b).replace(/[\xc0-\xff][\x80-\xbf]*/g,k)}}(""+void 0==typeof global?""+void 0==typeof self?this:self:global)

नीचे स्रोत कोड का उपयोग इसे उत्पन्न करने के लिए किया गया है।

var fromCharCode = String.fromCharCode;
var btoaUTF8 = (function(btoa, replacer){"use strict";
    return function(inputString, BOMit){
        return btoa((BOMit ? "\xEF\xBB\xBF" : "") + inputString.replace(
            /[\x80-\uD7ff\uDC00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, replacer
        ));
    }
})(btoa, function(nonAsciiChars){"use strict";
    // make the UTF string into a binary UTF-8 encoded string
    var point = nonAsciiChars.charCodeAt(0);
    if (point >= 0xD800 && point <= 0xDBFF) {
        var nextcode = nonAsciiChars.charCodeAt(1);
        if (nextcode !== nextcode) // NaN because string is 1 code point long
            return fromCharCode(0xef/*11101111*/, 0xbf/*10111111*/, 0xbd/*10111101*/);
        // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
        if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
            point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
            if (point > 0xffff)
                return fromCharCode(
                    (0x1e/*0b11110*/<<3) | (point>>>18),
                    (0x2/*0b10*/<<6) | ((point>>>12)&0x3f/*0b00111111*/),
                    (0x2/*0b10*/<<6) | ((point>>>6)&0x3f/*0b00111111*/),
                    (0x2/*0b10*/<<6) | (point&0x3f/*0b00111111*/)
                );
        } else return fromCharCode(0xef, 0xbf, 0xbd);
    }
    if (point <= 0x007f) return nonAsciiChars;
    else if (point <= 0x07ff) {
        return fromCharCode((0x6<<5)|(point>>>6), (0x2<<6)|(point&0x3f));
    } else return fromCharCode(
        (0xe/*0b1110*/<<4) | (point>>>12),
        (0x2/*0b10*/<<6) | ((point>>>6)&0x3f/*0b00111111*/),
        (0x2/*0b10*/<<6) | (point&0x3f/*0b00111111*/)
    );
});

फिर, बेस 64 डेटा को डीकोड करने के लिए, या तो HTTP को डेटा यूआरआई के रूप में प्राप्त होता है या नीचे दिए गए फ़ंक्शन का उपयोग करता है।

var clz32 = Math.clz32 || (function(log, LN2){"use strict";
    return function(x) {return 31 - log(x >>> 0) / LN2 | 0};
})(Math.log, Math.LN2);
var fromCharCode = String.fromCharCode;
var atobUTF8 = (function(atob, replacer){"use strict";
    return function(inputString, keepBOM){
        inputString = atob(inputString);
        if (!keepBOM && inputString.substring(0,3) === "\xEF\xBB\xBF")
            inputString = inputString.substring(3); // eradicate UTF-8 BOM
        // 0xc0 => 0b11000000; 0xff => 0b11111111; 0xc0-0xff => 0b11xxxxxx
        // 0x80 => 0b10000000; 0xbf => 0b10111111; 0x80-0xbf => 0b10xxxxxx
        return inputString.replace(/[\xc0-\xff][\x80-\xbf]*/g, replacer);
    }
})(atob, function(encoded){"use strict";
    var codePoint = encoded.charCodeAt(0) << 24;
    var leadingOnes = clz32(~codePoint);
    var endPos = 0, stringLen = encoded.length;
    var result = "";
    if (leadingOnes < 5 && stringLen >= leadingOnes) {
        codePoint = (codePoint<<leadingOnes)>>>(24+leadingOnes);
        for (endPos = 1; endPos < leadingOnes; ++endPos)
            codePoint = (codePoint<<6) | (encoded.charCodeAt(endPos)&0x3f/*0b00111111*/);
        if (codePoint <= 0xFFFF) { // BMP code point
          result += fromCharCode(codePoint);
        } else if (codePoint <= 0x10FFFF) {
          // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
          codePoint -= 0x10000;
          result += fromCharCode(
            (codePoint >> 10) + 0xD800,  // highSurrogate
            (codePoint & 0x3ff) + 0xDC00 // lowSurrogate
          );
        } else endPos = 0; // to fill it in with INVALIDs
    }
    for (; endPos < stringLen; ++endPos) result += "\ufffd"; // replacement character
    return result;
});

अधिक मानक होने का लाभ यह है कि यह एनकोडर और यह डिकोडर अधिक व्यापक रूप से लागू होते हैं क्योंकि उनका उपयोग एक मान्य URL के रूप में किया जा सकता है जो सही ढंग से प्रदर्शित होता है। ध्यान से देखें।

(function(window){
    "use strict";
    var sourceEle = document.getElementById("source");
    var urlBarEle = document.getElementById("urlBar");
    var mainFrameEle = document.getElementById("mainframe");
    var gotoButton = document.getElementById("gotoButton");
    var parseInt = window.parseInt;
    var fromCodePoint = String.fromCodePoint;
    var parse = JSON.parse;
    
    function unescape(str){
        return str.replace(/\\u[\da-f]{0,4}|\\x[\da-f]{0,2}|\\u{[^}]*}|\\[bfnrtv"'\\]|\\0[0-7]{1,3}|\\\d{1,3}/g, function(match){
          try{
            if (match.startsWith("\\u{"))
              return fromCodePoint(parseInt(match.slice(2,-1),16));
            if (match.startsWith("\\u") || match.startsWith("\\x"))
              return fromCodePoint(parseInt(match.substring(2),16));
            if (match.startsWith("\\0") && match.length > 2)
              return fromCodePoint(parseInt(match.substring(2),8));
            if (/^\\\d/.test(match)) return fromCodePoint(+match.slice(1));
          }catch(e){return "\ufffd".repeat(match.length)}
          return parse('"' + match + '"');
        });
    }
    
    function whenChange(){
      try{ urlBarEle.value = "data:text/plain;charset=UTF-8;base64," + btoaUTF8(unescape(sourceEle.value), true);
      } finally{ gotoURL(); }
    }
    sourceEle.addEventListener("change",whenChange,{passive:1});
    sourceEle.addEventListener("input",whenChange,{passive:1});
    
    // IFrame Setup:
    function gotoURL(){mainFrameEle.src = urlBarEle.value}
    gotoButton.addEventListener("click", gotoURL, {passive: 1});
    function urlChanged(){urlBarEle.value = mainFrameEle.src}
    mainFrameEle.addEventListener("load", urlChanged, {passive: 1});
    urlBarEle.addEventListener("keypress", function(evt){
      if (evt.key === "enter") evt.preventDefault(), urlChanged();
    }, {passive: 1});
    
        
    var fromCharCode = String.fromCharCode;
    var btoaUTF8 = (function(btoa, replacer){
		    "use strict";
        return function(inputString, BOMit){
        	return btoa((BOMit?"\xEF\xBB\xBF":"") + inputString.replace(
        		/[\x80-\uD7ff\uDC00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, replacer
    		));
    	}
    })(btoa, function(nonAsciiChars){
		"use strict";
    	// make the UTF string into a binary UTF-8 encoded string
    	var point = nonAsciiChars.charCodeAt(0);
    	if (point >= 0xD800 && point <= 0xDBFF) {
    		var nextcode = nonAsciiChars.charCodeAt(1);
    		if (nextcode !== nextcode) { // NaN because string is 1code point long
    			return fromCharCode(0xef/*11101111*/, 0xbf/*10111111*/, 0xbd/*10111101*/);
    		}
    		// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
    		if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
    			point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
    			if (point > 0xffff) {
    				return fromCharCode(
    					(0x1e/*0b11110*/<<3) | (point>>>18),
    					(0x2/*0b10*/<<6) | ((point>>>12)&0x3f/*0b00111111*/),
    					(0x2/*0b10*/<<6) | ((point>>>6)&0x3f/*0b00111111*/),
    					(0x2/*0b10*/<<6) | (point&0x3f/*0b00111111*/)
    				);
    			}
    		} else {
    			return fromCharCode(0xef, 0xbf, 0xbd);
    		}
    	}
    	if (point <= 0x007f) { return inputString; }
    	else if (point <= 0x07ff) {
    		return fromCharCode((0x6<<5)|(point>>>6), (0x2<<6)|(point&0x3f/*00111111*/));
    	} else {
    		return fromCharCode(
    			(0xe/*0b1110*/<<4) | (point>>>12),
    			(0x2/*0b10*/<<6) | ((point>>>6)&0x3f/*0b00111111*/),
    			(0x2/*0b10*/<<6) | (point&0x3f/*0b00111111*/)
    		);
    	}
    });
    setTimeout(whenChange, 0);
})(window);
img:active{opacity:0.8}
<center>
<textarea id="source" style="width:66.7vw">Hello \u1234 W\186\0256ld!
Enter text into the top box. Then the URL will update automatically.
</textarea><br />
<div style="width:66.7vw;display:inline-block;height:calc(25vw + 1em + 6px);border:2px solid;text-align:left;line-height:1em">
<input id="urlBar" style="width:calc(100% - 1em - 13px)" /><img id="gotoButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAeCAMAAADqx5XUAAAAclBMVEX///9NczZ8e32ko6fDxsU/fBoSQgdFtwA5pAHVxt+7vLzq5ex23y4SXABLiiTm0+/c2N6DhoQ6WSxSyweVlZVvdG/Uz9aF5kYlbwElkwAggACxs7Jl3hX07/cQbQCar5SU9lRntEWGum+C9zIDHwCGnH5IvZAOAAABmUlEQVQoz7WS25acIBBFkRLkIgKKtOCttbv//xdDmTGZzHv2S63ltuBQQP4rdRiRUP8UK4wh6nVddQwj/NtDQTvac8577zTQb72zj65/876qqt7wykU6/1U6vFEgjE1mt/5LRqrpu7oVsn0sjZejMfxR3W/yLikqAFcUx93YxLmZGOtElmEu6Ufd9xV3ZDTGcEvGLbMk0mHHlUSvS5svCwS+hVL8loQQyfpI1Ay8RF/xlNxcsTchGjGDIuBG3Ik7TMyNxn8m0TSnBAK6Z8UZfp3IbAonmJvmsEACum6aNv7B0CnvpezDcNhw9XWsuAr7qnRg6dABmeM4dTgn/DZdXWs3LMspZ1KDMt1kcPJ6S1icWNp2qaEmjq6myx7jbQK3VKItLJaW5FR+cuYlRhYNKzGa9vF4vM5roLW3OSVjkmiGJrPhUq301/16pVKZRGFYWjTP50spTxBN5Z4EKnSonruk+n4tUokv1aJSEl/MLZU90S3L6/U6o0J142iQVp3HcZxKSo8LfkNRCtJaKYFSRX7iaoAAUDty8wvWYR6HJEepdwAAAABJRU5ErkJggg==" style="width:calc(1em + 4px);line-height:1em;vertical-align:-40%;cursor:pointer" />
<iframe id="mainframe" style="width:66.7vw;height:25vw" frameBorder="0"></iframe>
</div>
</center>

बहुत मानकीकृत होने के अलावा, उपरोक्त कोड स्निपेट भी बहुत तेज़ हैं। उत्तराधिकार की एक अप्रत्यक्ष श्रृंखला के बजाय जहां डेटा को कई रूपों (जैसे कि रिकार्डो गली की प्रतिक्रिया) के बीच कई बार परिवर्तित करना पड़ता है, उपरोक्त कोड स्निपेट प्रत्यक्ष रूप से यथासंभव संभव है। यह String.prototype.replaceएन्कोडिंग करते समय डेटा को संसाधित करने के लिए केवल एक सरल फास्ट कॉल का उपयोग करता है , और डिकोडिंग के समय केवल डेटा को डीकोड करने के लिए। एक और प्लस यह है (विशेष रूप से बड़े तार के लिए), String.prototype.replaceब्राउज़र स्ट्रिंग को आकार देने के अंतर्निहित मेमोरी प्रबंधन को स्वचालित रूप से संभालने की अनुमति देता है, जिससे क्रोम और फ़ायरफ़ॉक्स जैसे सदाबहार ब्राउज़रों में एक महत्वपूर्ण प्रदर्शन को बढ़ावा मिलता है जो भारी अनुकूलन करता हैString.prototype.replace। अंत में, केक पर आइसिंग यह है कि आपके लिए लैटिन स्क्रिप्ट exclīsīv, उपयोगकर्ताओं के लिए, स्ट्रिंग जिनमें 0x7f से ऊपर कोई कोड बिंदु नहीं है, प्रक्रिया के लिए अतिरिक्त तेज़ हैं क्योंकि स्ट्रिंग प्रतिस्थापन एल्गोरिदम द्वारा अनमॉडिफ़ाइड रहती है।

मैंने इस समाधान के लिए https://github.com/anonyco/BestBase64EncoderDecoder/ पर एक github रिपॉजिटरी बनाई है


क्या आप "उपयोगकर्ता द्वारा बनाए गए तरीके" बनाम "ब्राउज़र द्वारा व्याख्या करने योग्य" के अर्थ पर विस्तार से बता सकते हैं? इस समाधान का उपयोग करने का मूल्य-वर्धन क्या है, कहते हैं, मोज़िला क्या सलाह देता है?
ब्रैंडनस्क्रिप्ट

@brandonscript मोज़िला एमडीएन से अलग है। MDN उपयोगकर्ता-निर्मित सामग्री है। MDN का वह पृष्ठ जो आपके समाधान की अनुशंसा करता है, उपयोगकर्ता-निर्मित सामग्री थी, न कि ब्राउज़र विक्रेता द्वारा बनाई गई सामग्री।
जैक गिफिन

क्या आपका समाधान विक्रेता बनाया गया है? मुझे ऐसा लगता है, मैं मूल को श्रेय देना चाहूंगा। यदि नहीं, तो यह भी उपयोगकर्ता-निर्मित है, और एमडीएन के उत्तर से अलग नहीं है?
ब्रैंडनस्क्रिप्ट

@brandonscript अच्छी बात। तुम सही हो। मैंने पाठ का वह टुकड़ा निकाल दिया। इसके अलावा, मेरे द्वारा जोड़े गए डेमो को देखें।
जैक गिफिन

0

छोटे सुधार, अनस्केप और पलायन को हटा दिया जाता है, इसलिए:

function utf8_to_b64( str ) {
    return window.btoa(decodeURIComponent(encodeURIComponent(str)));
}

function b64_to_utf8( str ) {
     return decodeURIComponent(encodeURIComponent(window.atob(str)));
}


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

2
ऐसा लगता है कि डॉक्टर लिंक अब इससे अलग है, इसे प्रबंधित करने के लिए एक रेगेक्स समाधान सुझा रहा है।
ब्रांडनस्क्रिप्ट

2
यह काम नहीं करेगा, क्योंकि encodeURIComponentइसका उलटा है decodeURIComponent, अर्थात यह सिर्फ रूपांतरण को पूर्ववत करेगा। क्या हो रहा है और क्या के एक महान विवरण के लिए stackoverflow.com/a/31412163/1534459 देखें । escapeunescape
बोडो

1
@canaaerus मुझे आपकी टिप्पणी समझ में नहीं आती है? भागने और unescape को हटा दिया जाता है, मैं बस उन्हें [डिकोड | एनकोड] URIComponent फ़ंक्शन के साथ स्वैप करता हूं :-) सब कुछ ठीक है। पहले प्रश्न पढ़ें
डार्क

1
@Darkves: जिस कारण encodeURIComponentसे उपयोग किया जाता है, वह सही तरीके से (पूरी रेंज की) यूनिकोड स्ट्रिंग्स को संभालना है। इसलिए उदा window.btoa(decodeURIComponent(encodeURIComponent('€')))देता है Error: String contains an invalid characterक्योंकि यह समान है window.btoa('€')और btoaइसे एनकोड नहीं किया जा सकता
बॉडो

2
@Darkves: हाँ, यह सही है। लेकिन आप DecodeURIComponent के साथ EncodeURIComponent और unescape से बच नहीं सकते, क्योंकि Encode और भागने के तरीके एक ही काम नहीं करते हैं। डिकोड और अनस्केप के साथ भी। मैं मूल रूप से एक ही गलती की, btw। आपको ध्यान देना चाहिए कि यदि आप एक स्ट्रिंग लेते हैं, तो इसे UriEncode करें, फिर इसे UriDecode करें, आपको वही स्ट्रिंग वापस मिलती है जिसे आपने इनपुट किया था। तो ऐसा करना बकवास होगा। जब आप एक स्ट्रिंग को एनकोडर्कोम्पोनेंट के साथ एन्कोड किया जाता है, तो आपको वही स्ट्रिंग वापस नहीं मिलती है जिसे आपने इनपुट किया था, इसीलिए यह भागने / अनस्केप के साथ काम करता है, लेकिन आपके साथ नहीं।
स्टीफन स्टीगर

0

यहां उन ब्राउजरों के लिए कुछ भविष्य-प्रूफ कोड हैं जिनकी कमी हो सकती है escape/unescape()। ध्यान दें कि IE 9 और पुराने समर्थन नहीं करते हैं atob/btoa(), इसलिए आपको उनके लिए कस्टम बेस 64 कार्यों का उपयोग करने की आवश्यकता होगी।

// Polyfill for escape/unescape
if( !window.unescape ){
    window.unescape = function( s ){
        return s.replace( /%([0-9A-F]{2})/g, function( m, p ) {
            return String.fromCharCode( '0x' + p );
        } );
    };
}
if( !window.escape ){
    window.escape = function( s ){
        var chr, hex, i = 0, l = s.length, out = '';
        for( ; i < l; i ++ ){
            chr = s.charAt( i );
            if( chr.search( /[A-Za-z0-9\@\*\_\+\-\.\/]/ ) > -1 ){
                out += chr; continue; }
            hex = s.charCodeAt( i ).toString( 16 );
            out += '%' + ( hex.length % 2 != 0 ? '0' : '' ) + hex;
        }
        return out;
    };
}

// Base64 encoding of UTF-8 strings
var utf8ToB64 = function( s ){
    return btoa( unescape( encodeURIComponent( s ) ) );
};
var b64ToUtf8 = function( s ){
    return decodeURIComponent( escape( atob( s ) ) );
};

UTF-8 एन्कोडिंग और डिकोडिंग के लिए एक अधिक व्यापक उदाहरण यहां पाया जा सकता है: http://jsfiddle.net/47zwb41o/


-1

उपरोक्त समाधान सहित यदि अभी भी समस्या का सामना करना पड़ रहा है तो नीचे दिए गए प्रयास पर ध्यान दें, जहां टीएस के लिए भागने का समर्थन नहीं किया गया है।

blob = new Blob(["\ufeff", csv_content]); // this will make symbols to appears in excel 

csv_content के लिए आप नीचे की तरह प्रयास कर सकते हैं।

function b64DecodeUnicode(str: any) {        
        return decodeURIComponent(atob(str).split('').map((c: any) => {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.