Base64 kodunu çözmek için Javascript'in atob'unu kullanmak, utf-8 dizelerinin kodunu doğru şekilde çözmüyor


108

window.atob()Base64 olarak kodlanmış bir dizenin kodunu çözmek için Javascript işlevini kullanıyorum (özellikle GitHub API'den base64 kodlu içerik). Sorun, ASCII kodlu karakterleri geri alıyorum ( â¢yerine gibi ). Utf-8 olarak kodu çözülecek şekilde gelen base64 ile kodlanmış akışı nasıl düzgün bir şekilde işleyebilirim?


3
Bağlandığınız MDN sayfasında "Unicode veya UTF-8 dizeleriyle kullanım için" ifadesiyle başlayan bir paragraf var.
Pointy

1
Düğümde misin? Bundan daha iyi çözümler varatob
Bergi

Yanıtlar:


274

Bir var harika makale tam olarak bu sorunu açıklanır Mozilla'nın MDN docs tarih:

"Unicode Sorunu" DOMStrings 16 bit kodlu dizeler olduğundan, çoğu tarayıcıda window.btoabir Unicode dizesini çağırmak , Character Out Of Range exceptionbir karakterin 8 bitlik bayt aralığını (0x00 ~ 0xFF) aşması durumunda a neden olur . Bu sorunu çözmek için iki olası yöntem vardır:

  • ilki, tüm dizeden kaçış yapmaktır (UTF-8 ile bakın encodeURIComponent) ve sonra onu kodlamaktır;
  • ikincisi UTF-16'yı DOMStringUTF-8 karakter dizisine dönüştürmek ve sonra onu kodlamaktır.

Önceki çözümlere ilişkin bir not: MDN makalesi başlangıçta istisna sorununun kullanılmasını unescapeve escapeçözülmesini önerdi Character Out Of Range, ancak o zamandan beri kullanımdan kaldırıldı. Buradaki bazı diğer cevaplar bunun etrafında çalışmayı önerdi decodeURIComponentve encodeURIComponentbunun güvenilmez ve öngörülemez olduğu kanıtlandı. Bu cevaba yapılan en son güncelleme, hızı artırmak ve kodu modernize etmek için modern JavaScript işlevlerini kullanır.

Kendinize biraz zaman kazandırmaya çalışıyorsanız, bir kitaplık kullanmayı da düşünebilirsiniz:

UTF8 ⇢ base64 kodlama

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=="

Base64 ⇢ UTF8 kod çözme

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 öncesi çözüm (işlevsel ve eski tarayıcılar için muhtemelen daha iyi destek olsa da, güncel değil)

@ MA-Maddin aracılığıyla bazı ek TypeScript uyumluluğu ile doğrudan MDN'den gelen mevcut öneri:

// 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"

Orijinal çözüm (kullanımdan kaldırıldı)

Bu kullanıldı escapeve unescape(artık kullanımdan kaldırıldı, ancak tüm modern tarayıcılarda hala çalışıyor):

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"

Ve son bir şey: Bu sorunla ilk olarak GitHub API'yi çağırırken karşılaştım. Bunun (Mobil) Safari'de düzgün bir şekilde çalışmasını sağlamak için , kaynağı bile çözmeden önce tüm beyaz alanı base64 kaynağından çıkarmak zorunda kaldım . Bunun 2017'de hala geçerli olup olmadığını bilmiyorum:

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

1
w3schools.com/jsref/jsref_unescape.asp "Unescape () işlevi JavaScript 1.5 sürümünde kaldırılmıştır. Bunun yerine decodeURI () veya decodeURIComponent () kullanın."
Tedd Hansen

1
Günlerimi kurtardın, kardeşim
Bay Neo

2
Güncelleme:b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=');
MDN'deki

2
decodeURIComponent(atob('4pyTIMOgIGxhIG1vZGU=').split('').map(x => '%' + x.charCodeAt(0).toString(16)).join('')) Kod çözmenin başka bir yolu da en yüksek performanslı kod değil, ama ne olduğu.
daniel.gindi

2
return String.fromCharCode(parseInt(p1, 16));TypeScript uyumluluğuna sahip olmak.
Martin Schneider

21

Bir şeyler değişir. Kaçış / çıkış yapılmış yöntemler kullanımdan kaldırıldı.

Dizeyi Base64 olarak kodlamadan önce URI kodlayabilirsiniz. Bunun Base64 kodlu UTF8 üretmediğini, bunun yerine Base64 kodlu URL kodlu verileri ürettiğini unutmayın. Her iki taraf da aynı kodlama üzerinde anlaşmalıdır.

Buradaki çalışma örneğine bakın: http://codepen.io/anon/pen/PZgbPW

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

OP'nin sorunu için, js-base64 gibi bir üçüncü taraf kitaplığı sorunu çözmelidir.


1
Girdi dizesinin base64'ünü değil kodlanmış bileşenini ürettiğinizi belirtmek isterim. Yani eğer onu gönderirseniz, diğer taraf onu "base64" olarak çözemez ve orijinal dizeyi alamaz
Riccardo Galli

3
Haklısın, bunu belirtmek için metni güncelledim. Teşekkürler. Alternatif olarak, üçüncü taraf bir kitaplık kullanarak (js-base64 gibi) veya "Hata: 'Pencerede' btoa 'çalıştırılamadı: Kodlanacak dizge Latin1 aralığı dışındaki karakterler içeriyor. "
Tedd Hansen

14

Dizeleri bayt olarak ele almak sizin işinizse, aşağıdaki işlevleri kullanabilirsiniz

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
Teşekkürler. Cevabınız, bu işe yaramama yardımcı olmak için çok önemliydi ve bu da birkaç günden fazla saatlerimi aldı. +1. stackoverflow.com/a/51814273/470749
Ryan

Çok daha hızlı ve daha fazla tarayıcılar arası çözüm için (ancak esasen aynı çıktı), lütfen stackoverflow.com/a/53433503/5601591
Jack Giffin

u_atob ve u_btoa, IE10 (2012) 'den beri her tarayıcıda mevcut olan işlevleri kullanıyor, bana sağlam görünüyor (TextEncoder'a atıfta bulunursanız, bu sadece bir örnek)
Riccardo Galli

5

İşte Mozilla Geliştirme Kaynaklarında açıklandığı gibi 2018 güncellenmiş çözümü

UNICODE'DAN B64'E KODLAMAK İÇİN

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'DEN UNICODE'A DÖNÜŞTÜRMEK İÇİN

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"

5

Benim için çalışan makalenin tamamı: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding

Unicode / UTF-8'den kodladığımız bölüm

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"

Bu günümüzde en çok kullanılan yöntemlerden biridir.


3

Yaygın olarak kullanılabilen bir base64 URI üreten bir çözüm isteyebileceğini varsayıyorum. Lütfen data:text/plain;charset=utf-8;base64,4pi44pi54pi64pi74pi84pi+4pi/bir demo görmek için ziyaret edin (veri uri'sini kopyalayın, yeni bir sekme açın, veri URI'sini adres çubuğuna yapıştırın ve sayfaya gitmek için enter tuşuna basın). Bu URI'nin base64 olarak kodlanmış olmasına rağmen, tarayıcı hala yüksek kod noktalarını tanıyabilir ve bunları düzgün bir şekilde çözebilir. Küçültülmüş kodlayıcı + kod çözücü 1058 bayttır (+ Gzip → 589 bayt)

!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)

Bunu oluşturmak için kullanılan kaynak kodu aşağıdadır.

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*/)
    );
});

Ardından, base64 verilerinin kodunu çözmek için HTTP, verileri bir veri URI'si olarak alır veya aşağıdaki işlevi kullanın.

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;
});

Daha standart olmanın avantajı, bu kodlayıcı ve bu kod çözücünün daha geniş çapta uygulanabilir olmasıdır çünkü bunlar doğru şekilde görüntülenen geçerli bir URL olarak kullanılabilir. Gözlemek.

(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>

Çok standart hale getirilmesinin yanı sıra, yukarıdaki kod parçacıkları da çok hızlıdır. Verilerin çeşitli biçimler arasında (Riccardo Galli'nin yanıtı gibi) birkaç kez dönüştürülmesi gereken dolaylı bir ardışık zincir yerine, yukarıdaki kod parçacığı, performans açısından mümkün olduğu kadar doğrudandır. Sadece bir basit hızlı kullanırString.prototype.replaceKodlama sırasında verileri işlemek için çağrı ve kod çözme sırasında verileri çözmek için yalnızca bir tane kullanır. Diğer bir artı da (özellikle büyük dizeler için), String.prototype.replacetarayıcının dizeyi yeniden boyutlandırmanın temeldeki bellek yönetimini otomatik olarak işlemesine izin vererek, özellikle Chrome ve Firefox gibi yoğun bir şekilde optimize eden her zaman yeşil tarayıcılarda önemli bir performans artışı sağlar.String.prototype.replace. Son olarak, pastadaki krema, siz latin komut dosyası kullanıcıları hariç, 0x7f'nin üzerinde herhangi bir kod noktası içermeyen dizelerin işlenmesi çok hızlıdır çünkü dizge değiştirme algoritması tarafından değiştirilmeden kalır.

Bu çözüm için https://github.com/anonyco/BestBase64EncoderDecoder/ adresinde bir github deposu oluşturdum.


"Kullanıcı tarafından oluşturulan yöntem" ile "tarayıcı tarafından yorumlanabilir" ile ne demek istediğinizi açıklar mısınız? Bu çözümü kullanmanın katma değeri nedir, mesela Mozilla'nın önerdiği şey nedir?
brandonscript

@brandonscript Mozilla, MDN'den farklıdır. MDN, kullanıcı tarafından oluşturulan içeriktir. Çözümünüzü öneren MDN sayfası, tarayıcı satıcısının oluşturduğu içerik değil, kullanıcı tarafından oluşturulan içerikti.
Jack Giffin

Çözüm satıcınız oluşturuldu mu? Öyleyse, kökene kredi vermeyi öneririm. Değilse, o zaman da kullanıcı tarafından oluşturulmuş ve MDN'nin cevabından farklı değil mi?
brandonscript

@brandonscript İyi nokta. Haklısın. O metni kaldırdım. Ayrıca eklediğim demoya göz atın.
Jack Giffin

0

Küçük düzeltme, unescape ve kaçış kullanımdan kaldırıldı, bu nedenle:

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
Görünüşe göre doküman bağlantısı şimdi bundan farklı ve onu yönetmek için bir normal ifade çözümü öneriyor.
brandonscript

2
Bu işe yaramayacak, çünkü encodeURIComponentbunun tersidir decodeURIComponent, yani sadece dönüşümü geri alacaktır. Bkz stackoverflow.com/a/31412163/1534459 ile neler olduğu büyük bir açıklama için escapeve unescape.
bodo

1
@canaaerus Yorumunuzu anlamadım? escape ve unescape kullanımdan kaldırıldı, onları sadece [decode | encode] URIComponent işlevi ile değiştiriyorum :-) Her şey yolunda gidiyor. Önce soruyu okuyun
Darkves

1
@Darkves: Kullanılmasının nedeni encodeURIComponent, (tüm aralığı) unicode dizelerini doğru şekilde işlemektir. Yani örneğin window.btoa(decodeURIComponent(encodeURIComponent('€')))verir Error: String contains an invalid characterçünkü kodlayamaz window.btoa('€')ve aynıdır . btoa
bodo

2
@Darkves: Evet, bu doğru. Ancak EncodeURIComponent ile escape ve DecodeURIComponent ile unescape'i değiştiremezsiniz çünkü Encode ve escape yöntemleri aynı şeyi yapmaz. Kod çözme ve unescape ile aynı. Başlangıçta aynı hatayı yaptım, btw. Bir dizge alırsanız, UriEncode ve sonra UriDecode alırsanız, girdiğiniz dizenin aynısını geri alırsınız. Yani bunu yapmak saçma olurdu. EncodeURIComponent ile kodlanmış bir dizgeyi geri aldığınızda, girdiğiniz dizgenin aynısını geri alamazsınız, bu yüzden escape / unescape ile çalışır, ancak sizinkinde çalışmaz.
Stefan Steiger

0

Eksik olabilecek tarayıcılar için geleceğe yönelik bazı kodlar escape/unescape(). IE 9 ve daha eski sürümlerin desteklemediğini atob/btoa(), bu nedenle onlar için özel base64 işlevlerini kullanmanız gerektiğini unutmayın.

// 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 kodlama ve kod çözme için daha kapsamlı bir örnek burada bulunabilir: http://jsfiddle.net/47zwb41o/


-1

Yukarıdaki çözümü de içeren hala sorunla karşılaşıyorsanız aşağıdaki gibi deneyin, TS için kaçışın desteklenmediği durumu göz önünde bulundurun.

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

csv_content için aşağıdaki gibi deneyebilirsiniz.

function b64DecodeUnicode(str: any) {        
        return decodeURIComponent(atob(str).split('').map((c: any) => {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.