'উইন্ডো' তে 'বিটিওএ' চালানোতে ব্যর্থ: এনকোড করা স্ট্রিংটিতে ল্যাটিন 1 ব্যাপ্তির বাইরের অক্ষর রয়েছে।


133

আমার পরীক্ষাগুলি অনুসারে শিরোনামের ত্রুটিটি কেবল গুগল ক্রোমে নিক্ষেপ করা হয়েছে। আমি বেস বড় 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 লুকিয়ে আছে যদি ইফ্রমে থাকে।

এই ত্রুটিটি আসলে বেশ পরিবর্তন কারণ সাধারণত, গুগল ক্রোম btoaকল করার সময় ক্রাশ হয়ে যায় । মোজিলা ফায়ারফক্সের এখানে কোনও সমস্যা নেই তাই সমস্যাটি ব্রাউজার সম্পর্কিত। আমি ফাইলের কোনও অদ্ভুত চরিত্র সম্পর্কে অবগত নই। আসলে আমি বিশ্বাস করি যে অ-এস্কি অক্ষর নেই।

প্রশ্ন: আমি কীভাবে সমস্যাযুক্ত চরিত্রগুলি সন্ধান করব এবং সেগুলি প্রতিস্থাপন করব যাতে ক্রোম অভিযোগ করা বন্ধ করে দেয়?

ডাউনলোডটি শুরু করার জন্য আমি ডাউনলোডিফাই ব্যবহার করার চেষ্টা করেছি, তবে এটি কার্যকর হয় না। এটি অবিশ্বাস্য এবং ডিবাগের অনুমতি দেওয়ার জন্য কোনও ত্রুটি নিক্ষেপ করে।

উত্তর:


212

আপনার যদি ইউটিএফ 8 থাকে তবে এটি ব্যবহার করুন (আসলে এসভিজি উত্সের সাথে কাজ করে), যেমন:

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 আপডেট

এই সমস্যাটি আমাকে আবার বাগিয়ে দিচ্ছে।
সহজ সত্যটি হল, অ্যাটব সত্যই ইউটিএফ 8-স্ট্রিংগুলি পরিচালনা করে না - এটি কেবলমাত্র ASCII।
এছাড়াও, আমি জেএস-বেস 64 এর মতো ব্লাটওয়্যার ব্যবহার করব না।
তবে ওয়েব টোকলিতে একটি ছোট, সুন্দর এবং খুব রক্ষণাবেক্ষণযোগ্য বাস্তবায়ন রয়েছে:

/**
*
*  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 (hex 0x7F) এর সমান বা নীচের যে কোনও অক্ষরের জন্য, ইউটিএফ -8 উপস্থাপনাটি একটি বাইট। এটি সম্পূর্ণ ইউনিকোড মূল্যের সর্বনিম্ন 7 বিট। এটি ASCII মান হিসাবে একই।

  • 2047 (হেক্স 0x07FF) এর সমান বা নীচের অক্ষরের জন্য, ইউটিএফ -8 উপস্থাপনা দুটি বাইটে ছড়িয়ে পড়ে। প্রথম বাইটে দুটি উচ্চ বিট সেট এবং তৃতীয় বিট পরিষ্কার (অর্থাত 0xC2 থেকে 0xDF) থাকবে। দ্বিতীয় বাইটে শীর্ষ বিট সেট এবং দ্বিতীয় বিট পরিষ্কার হবে (অর্থাত 0x80 থেকে 0xBF)।

  • 2048 এর চেয়ে বেশি বা তার চেয়ে কম 65535 (0xFFFF) এর চেয়ে কম অক্ষরের জন্য, ইউটিএফ -8 উপস্থাপনাটি তিনটি বাইটে ছড়িয়ে রয়েছে।


6
আপনি কি এটি আরও কিছুটা উপস্থাপন করতে পারেন ... আমি পুরোপুরি হারিয়েছি
মুহাম্মদ উমর

আমি যদি আপনি থাকতাম তবে আমি কেবল কোডটি চালাতাম। escapeস্ট্রিংটিকে একটিতে রূপান্তর করে যা কেবলমাত্র url বৈধ অক্ষর ধারণ করে। এটি ত্রুটিগুলি রোধ করে।
টোমা জ্যাটো - মনিকা

6
escapeএবং unescapeজাভাস্ক্রিপ্ট 1.5 তে অবহেলা করা হয়েছিল এবং এর পরিবর্তে একটিকে যথাক্রমে encodeURIComponentবা ব্যবহার করা উচিত decodeURIComponent। আপনি একসাথে অবহেলিত এবং নতুন ফাংশন ব্যবহার করছেন। কেন? দেখুন: w3schools.com/jsref/jsref_escape.asp
লাইফ

2
@ লিফ: এটি কেবল সঠিকভাবে কাজ করে কারণ পলায়ন এবং আনস্কেপগুলি বগি (একইভাবে);)
স্টিফান স্টেইগার

8
ওয়েবপ্যাক ব্যবহার থেকে অন্য কেউ এখানে ক্ষতবিক্ষত হয়েছে?
অবিন্দ্র গলচরণ

18

সাথে ব্যবহার btoaকরা unescapeএবং encodeURIComponentআমার জন্য কাজ করে না। সমস্ত বিশেষ অক্ষরকে এক্সএমএল / এইচটিএমএল সত্তার সাথে প্রতিস্থাপন এবং তারপরে বেস 64 এর উপস্থাপনায় রূপান্তর করা আমার পক্ষে এই সমস্যাটি সমাধান করার একমাত্র উপায় ছিল। কিছু কোড:

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

1
যেহেতু আমি এই প্রশ্নটি পোস্ট করেছি আমি এমন API গুলি সম্পর্কে কিছুটা শিখলাম যা আমি যা করছি তার জন্য নিবেদিত। আপনি যে স্ট্রিংটি রূপান্তর করছেন তা যদি দীর্ঘ হয় Blobতবে রূপান্তরটি পরিচালনা করতে অবজেক্টটি ব্যবহার করুন । Blobযে কোনও বাইনারি ডেটা পরিচালনা করতে পারে।
টম্যা জ্যাটো - মনিকা

1
আই 9 সম্পর্কে নিশ্চিত নয়। তবে আমার ধারণা হ'ল আপনি যদি বেস 64 এর রূপান্তর ক্লায়েন্ট-সাইডের মতো জিনিসগুলি করেন তবে আপনি সম্ভবত আধুনিক ওয়েব-অ্যাপ তৈরি করছেন যা তাড়াতাড়ি বা পরে আধুনিক উপায়গুলির প্রয়োজন হবে। এছাড়াও, একটি ব্লব পলফিল আছে।
টম্যা জ্যাটো - মনোকা

1
@ ইটালোবোরস্যাটটো আপনি কিংবদন্তি!
কোডেপিক

1
@ ইটালোবার্সসাত্তো এটিই আমার জন্য কাজ করেছিল এমন একমাত্র সমাধান। ডি-এসভিজি চার্টটি ধরতে, এক্সএমএলসায়ারাইজার ব্যবহার করে এটি সিরিয়ালকরণ করতে, বেস -৪৪ এনকোডেড এএসসিআইআই স্ট্রিং তৈরি করতে এটি বিটিও () এটি (যেখানে আমি আপনার সমাধানটি ব্যবহার করেছি) এ পাস করার জন্য এটির দরকার হয়েছিল, তারপরে এটি চিত্রের উপাদানটিতে পাস করুন যা তারপরে ক্যানভাসে টানা এবং তারপরে রফতানি করুন যাতে আপনি সামনের প্রান্তে একটি চিত্র ডাউনলোড করতে পারেন। বরং সংশ্লেষিত এবং হ্যাকি সমাধান, তবে ব্যবহারকারীরা যখন কিছু গ্রাফিক্স ডাউনলোড করতে চান তখন সার্ভার-সাইড রেন্ডার চার্টের প্রয়োজন হয় না। আপনি যদি আগ্রহী হন তবে আমি আপনাকে কিছু কোডের নমুনা পাঠাতে পারি। মন্তব্যটি তাদের জন্য খুব সংক্ষিপ্ত
কোডেপিক

1
@ ইটালোবোর্স্যাটটো <এসভিজি এক্সএমএনএস = " ডব্লু3. org/2000/ svg " ভিউবক্স = "0 0 1060 105" প্রস্থ = "1060" উচ্চতা = "105"> <পথ শ্রেণি = "ডোমেন" স্ট্রোক = "কোনও" ডি = "এম -6,0.5H0.5V35.5H-6 "> <লাইন স্ট্রোক =" কিছুই নয় "x2 =" - 6 "y1 =" 0.5 "y2 =" 0.5 "পূরণ =" কিছুই নয় "স্ট্রোক-প্রস্থ =" 1px "ফন্ট- পরিবার = "সংস-সেরিফ" ফন্ট-আকার = "10px" /> <টেক্সট ফিল = "আরজিবি (196, 196, 196)" x = "- 9" y = "0.5" dy = "0.32 ম"> ভোগ এস্পানা - ভোগ এস্পা </ strong> <rect class = "প্রথম বার" পূরণ = "আরজিবি (25, 244, 71)" x = "0" y = "8" প্রস্থ = "790" উচ্চতা = "18" /> </ g> </svg> আমি অপ্রাসঙ্গিক টুকরো কেটে ফেলেছি। অপরাধী হ'ল ভোগ এস্পেনা -> an ব্রাউজারে কোনও চিত্র লোড হতে বাধা দেয়।
কোডেপিক

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

আমি কেবল ভেবেছিলাম যে কীভাবে সমস্যাটি আমি আসলে সমাধান করেছি এবং আমি কেন এটি সঠিক সমাধান বলে মনে করি (আপনি যদি পুরানো ব্রাউজারটির জন্য অনুকূল না হন তবে) share

ডেটা URL- এ ডেটা রূপান্তর করা ( 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);

ব্যবহারকারীদের ডেটা সংরক্ষণ করার অনুমতি দিচ্ছে

সুস্পষ্ট সমাধান ছাড়াও - ইউআরএল হিসাবে আপনার ডেটাআরএল দিয়ে নতুন উইন্ডো খোলার সাথে আপনি আরও দুটি জিনিস করতে পারেন।

1. fileSaver.js ব্যবহার করুন

ফাইল সেভার পূর্বনির্ধারিত ফাইলের নাম সহ প্রকৃত ফাইলসেভ ডায়ালগ তৈরি করতে পারে। এটি সাধারণ ডেটাআরএল পদ্ধতির কাছে ফ্যালব্যাকও করতে পারে।

2. ব্যবহার (পরীক্ষামূলক) URL.createObjectURL

এটি বেস 64 এনকোডড ডেটা পুনরায় ব্যবহারের জন্য দুর্দান্ত। এটি আপনার ডেটা URL এর জন্য একটি সংক্ষিপ্ত URL তৈরি করে:

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

নেতৃস্থানীয় blobউপসর্গ সহ URL টি ব্যবহার করতে ভুলবেন না । আমি document.bodyআবার ব্যবহার করেছি :

ছবির বর্ণনা

আপনি এই সংক্ষিপ্ত URL টি এজেএক্স লক্ষ্য, <script>উত্স বা <a>href অবস্থান হিসাবে ব্যবহার করতে পারেন । আপনি যদিও ইউআরএল নষ্ট করার জন্য দায়বদ্ধ:

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প্রস্তাব দেওয়া হয় না কারণ এটি ভবিষ্যতে অপসারণ করা যেতে পারে:

সতর্কতা : যদিও আনস্কেপ ()টিকে কঠোরভাবে অবচিত করা হয়নি (যেমন "ওয়েব স্ট্যান্ডার্ডগুলি থেকে সরানো হয়েছে"), এটি ইসিএমএ -২2২ স্ট্যান্ডার্ডের এনেক্সেক্স বিতে সংজ্ঞায়িত করা হয়েছে, যার পরিচিতিতে বলা হয়েছে:… এর মধ্যে বর্ণিত সমস্ত ভাষা বৈশিষ্ট্য এবং আচরণ সংযুক্তির এক বা একাধিক অযাচিত বৈশিষ্ট্য রয়েছে এবং উত্তরাধিকারের অনুপস্থিতিতে এই স্পেসিফিকেশনটি অপসারণ করা হবে।

দ্রষ্টব্য: ইউআরআই ডিকোড করতে ইউনস্কেপ ব্যবহার করবেন না, এর পরিবর্তে ডিকোডুরি বা ডিকোডিউরিউক উপাদানটি ব্যবহার করুন।


6
ফাংশনগুলি দেখতে ভাল লাগে তবে বেস প্রোটোটাইপগুলি বাড়ানো একটি খারাপ অভ্যাস।
টাইমমাচাইন 3030

4
জাভাস্ক্রিপ্ট একটি খারাপ অভ্যাস। আরও একটি হ্যাক কি, ধন্যবাদ।
rob5408

1
@ রব ৫৪০৮: যদিও আমি নীতিগতভাবে আপনার বক্তব্যের সাথে একমত, তবে আপনাকে আরও সতর্ক হওয়া উচিত: প্রোটোটাইপগুলি বিছিন্ন করে jQuery (অন্য একটি গ্রন্থাগার যা "আরও একটি হ্যাক" নীতি ব্যবহার করে)
স্টিফান স্টেইগার

@ স্টেফানস্টেইগার জেনে রাখা ভাল, অন্তর্দৃষ্টিটির জন্য ধন্যবাদ।
rob5408


2

btoa () কেবল স্ট্রিং.ফর্মকোডপয়েন্ট (0) থেকে স্ট্রিং.ফর্মকোডপয়েন্ট (255) পর্যন্ত অক্ষর সমর্থন করে। 256 বা ততোধিক কোড কোডযুক্ত বেস 64 অক্ষরের জন্য আপনাকে এগুলি আগে এবং পরে এনকোড / ডিকোড করতে হবে।

এবং এই সময়ে এটি কৃপণ হয়ে ওঠে ...

প্রতিটি সম্ভাব্য সাইন একটি ইউনিকোড-সারণিতে সাজানো হয়। ইউনিকোড-সারণিটি বিভিন্ন প্লেনগুলিতে বিভক্ত (ভাষা, গণিতের প্রতীক এবং আরও কিছু ...)। প্লেনে প্রতিটি চিহ্নের একটি স্বতন্ত্র কোড পয়েন্ট নম্বর থাকে। তাত্ত্বিকভাবে, সংখ্যাটি নির্বিচারে বড় হতে পারে।

একটি কম্পিউটার ডেটা বাইটে সঞ্চয় করে (8 বিট, হেক্সাডেসিমাল 0x00 - 0xff, বাইনারি 00000000 - 11111111, দশমিক 0 - 255)। এই সীমাটি সাধারণত বেসিক অক্ষরগুলি সংরক্ষণ করতে ব্যবহার করে (ল্যাটিন 1 রেঞ্জ)।

উচ্চতর কোডপয়েন্ট সহ অক্ষরের জন্য 255 টি বিভিন্ন এনকোডিং উপস্থিত রয়েছে। জাভাস্ক্রিপ্টে প্রতি চিহ্নে 16 টি বিট ব্যবহার করা হবে (ইউটিএফ -16), স্ট্রিংটি ডিওএমএসস্ট্রিং। ইউনিকোড 0x10fffff পর্যন্ত কোড পয়েন্টগুলি পরিচালনা করতে পারে। এর অর্থ, বেশ কয়েকটি বিট দূরে দূরে কয়েকটি বিট সংরক্ষণ করার জন্য একটি পদ্ধতির উপস্থিতি থাকতে হবে।

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

ইউটিএফ -১ দুটি 16 বিট কক্ষে 20 বিট সংরক্ষণ করতে সারোগেট জোড়া ব্যবহার করে। প্রথম উচ্চতর সারোগেটটি 110110XXXXXXXXX1 দিয়ে শুরু হয় , নীচের দ্বিতীয়টি 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/


দুর্দান্ত কাজ! stringToUTF8utf8ToString
You

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

তারপরে আপনার প্রিয় ওয়েব পরিদর্শকটি ব্যবহার করুন, কোডের লাইনে একটি ব্রেকপয়েন্ট দিন যা এই.লোডার.এসসিআরকে নির্ধারণ করে, তারপরে এই কোডটি কার্যকর করুন:

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

আপনার অ্যাপ্লিকেশনটির উপর নির্ভর করে, সীমার বাইরে থাকা অক্ষরগুলি প্রতিস্থাপন করা বা নাও কাজ করতে পারে, যেহেতু আপনি ডেটা পরিবর্তন করছেন। বিটিও পদ্ধতিতে ইউনিকোড অক্ষর সম্পর্কে MDN এ নোটটি দেখুন:

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.