ขนาดสูงสุดของค่า localStorage คืออะไร?


543

เนื่องจากlocalStorage(ปัจจุบัน) รองรับสตริงเป็นค่าเท่านั้นและเพื่อให้วัตถุต้องถูกทำให้เป็นสตริง (เก็บเป็นสตริง JSON) ก่อนที่จะสามารถจัดเก็บได้มีข้อ จำกัด ที่กำหนดเกี่ยวกับความยาวของค่า

ไม่มีใครทราบว่ามีคำจำกัดความที่ใช้กับเบราว์เซอร์ทั้งหมดหรือไม่


15
ฉันคิดว่าไม่มีใครตอบคำถาม "ยาวสูงสุดต่อมูลค่า" จริง ๆ
Pete Alvin

@PeteAlvin ฉันเพียงแค่ตอบคำถาม
user2428118

3
เบราว์เซอร์ทั้งหมด: html5rocks.com/th/tutorials/offline/quota-research
MCCCS

@PeteAlvin ใครบางคนตอบมันในปี 2015 คำตอบอื่น ๆ ที่อยู่ในข้อ จำกัด เรื่องขนาดรวม แต่ไม่ได้ จำกัด อยู่กับขนาดของมูลค่าต่อ
อาลี

คำตอบ:


421

การอ้างอิงจากบทความ Wikipedia เกี่ยวกับ Web Storage :

พื้นที่เก็บข้อมูลบนเว็บสามารถดูได้ง่ายว่าเป็นการปรับปรุงคุกกี้ให้ความจุมากขึ้น ( 10 MB ต่อแหล่งกำเนิดใน Google Chrome ( https://plus.google.com/u/0/+FrancoisBeaufort/posts/S5Q9HqDB8bh ), Mozilla Firefox และ Opera; 10 MB ต่อพื้นที่เก็บข้อมูลใน Internet Explorer ) และอินเตอร์เฟสแบบเป็นโปรแกรมที่ดีกว่า

และข้อความจากบทความของ John Resig [โพสต์มกราคม 2550]:

พื้นที่เก็บข้อมูล

โดยนัยแล้วด้วย DOM Storage คุณมีพื้นที่เก็บข้อมูลมากกว่าข้อ จำกัด ตัวแทนผู้ใช้ทั่วไปที่กำหนดไว้กับคุกกี้ อย่างไรก็ตามจำนวนเงินที่ให้ไว้ไม่ได้กำหนดไว้ในข้อมูลจำเพาะและไม่ได้ออกอากาศอย่างมีความหมายโดยตัวแทนผู้ใช้

หากคุณดูซอร์สโค้ด Mozilla เราจะเห็นว่า 5120KB เป็นขนาดหน่วยเก็บข้อมูลเริ่มต้นสำหรับทั้งโดเมน สิ่งนี้ทำให้คุณมีพื้นที่ในการทำงานมากกว่าคุกกี้ 2KB ทั่วไป

อย่างไรก็ตามขนาดของพื้นที่เก็บข้อมูลนี้สามารถปรับแต่งได้โดยผู้ใช้ (ดังนั้นพื้นที่จัดเก็บ 5MB ไม่ได้รับการรับรองและไม่ได้บอกเป็นนัย ๆ ) และตัวแทนผู้ใช้ (ตัวอย่างเช่น Opera อาจมีเพียง 3MB เท่านั้น - แต่เวลาเท่านั้นที่จะบอกได้ )


28
@Cupidvogel ไม่ก็หมายความว่าแต่ละคนdomain( origin) สามารถเก็บ 5MB ในไคลเอนต์ใด ๆ ข้อมูลถูกเก็บไว้ในเครื่องไคลเอนต์ - localStorageกลไกจะไม่โต้ตอบกับลูกค้า
DanielB

6
ไม่ฉันแค่ต้องการให้แน่ใจว่าข้อมูลเดียวกันสามารถเข้าถึงได้ในหลาย ๆ หน้าสำหรับโดเมนเดียวกัน บ่อยครั้งที่ฉันพบว่าโดเมนวลีและหน้าเว็บสะกดคำเหมือนกันดังนั้นอยากรู้แน่ ๆ !
SexyBeast

9
อย่างไรก็ตามมีข้อ จำกัด สำหรับค่าเดียวหรือไม่? (ถ้าฉันมีจำนวนมากของธงในการจัดเก็บเป็นวิธีการที่ปลอดภัยที่จะไปเก็บเป็น JSON ในคุณสมบัติเดียว?)
phtrivier

5
ฉันมี Safari ที่ 5MB และ Chrome 39 ที่ 10MB (ไม่แน่ใจว่าเมื่อใดที่เพิ่มขึ้นจาก 5MB) ดูบทความนี้html5rocks.com/en/tutorials/offline/quota-research
Ally

18
@Cupidvogel: ไม่มันไม่ได้อยู่ในโดเมนมันเป็นแหล่งกำเนิดเนื่องจากคำนี้ใช้กับนโยบายแหล่งกำเนิดเดียวกันและ: scheme + host + port http://example.comและhttps://example.comไม่ใช่ต้นกำเนิดเดียวกัน (รูปแบบที่แตกต่างกัน) http://example.comและhttp://www.example.comไม่ใช่ต้นกำเนิดเดียวกัน (โฮสต์ที่ต่างกัน) http://example.comและhttp://example.com:8080ไม่ได้มีจุดกำเนิดเดียวกัน (พอร์ตที่ต่างกัน) HTH :-)
TJ Crowder

134

ที่จริง Opera มีขนาดไม่เกิน 5MB มันเสนอให้เพิ่มขีด จำกัด ตามความต้องการใช้งานมากขึ้น ผู้ใช้สามารถเลือก "พื้นที่เก็บข้อมูลไม่ จำกัด " สำหรับโดเมน

คุณสามารถได้อย่างง่ายดายขีด จำกัด ของการทดสอบ localStorage / โควต้าของตัวเอง


50
ไม่ทำให้ Chrome ขัดข้องอีกต่อไป ... จุดที่น่าสนใจ: 5MB เท่ากับ 2.5 ล้านตัวอักษรบน Chrome เห็นได้ชัดว่า UFT16 ใช้สำหรับ localStore
เฟลิกซ์อัลคาลา

1
@ FelixAlcala แต่น่าเสียดายที่ Chrome ขัดข้อง 15.0.874.54 เบต้าบน Mac OS X ฉันมีปัญหาที่ 1.500.000 ตัวอักษร
Ivan Vučica

มันชุบโครมบนอุปกรณ์ของฉัน, และรีเซ็ต bckground, ไม่แปลกใจเลยที่โทรศัพท์ของฉันมี RAM เล็ก ๆ น้อย ๆ , มันไม่สามารถจัดการกับแอพพลิเคชั่น FLASHLIGHT ที่เปิดได้ขณะที่โครเมี่ยมเปิดอยู่
แจ็ค

6
@FelixAlcala - จริง UCS-2exposes ในขณะที่มันคล้ายกับUFT16มีความแตกต่างที่สำคัญมาก ... ส่วนใหญ่หมุนรอบข้อเท็จจริงที่ว่า UCS-2 ถือกำเนิด UFT
Jeremy J Starcher

@FelixAlcala คุณคิดว่าการแสดงจำนวนตัวอักษรและขนาดของดิสก์ที่เทียบเท่า (เช่น 2,700K ตัวอักษร ~ = 5,274 KB) เป็นความคิดที่ดีหรือไม่?
AJ Hsu

76

นี่เป็นสคริปต์ที่ตรงไปตรงมาสำหรับการค้นหาข้อ จำกัด :

if (localStorage && !localStorage.getItem('size')) {
    var i = 0;
    try {
        // Test up to 10 MB
        for (i = 250; i <= 10000; i += 250) {
            localStorage.setItem('test', new Array((i * 1024) + 1).join('a'));
        }
    } catch (e) {
        localStorage.removeItem('test');
        localStorage.setItem('size', i - 250);            
    }
}

ที่นี่เค้า , JSFiddleและโพสต์บล็อก

สคริปต์จะทดสอบการตั้งค่าสตริงข้อความที่ใหญ่ขึ้นเรื่อย ๆ จนกระทั่งเบราว์เซอร์มีข้อผิดพลาดเกิดขึ้น ณ จุดนั้นมันจะล้างข้อมูลการทดสอบและตั้งค่าขนาดสำคัญใน localStorage ที่เก็บขนาดเป็นกิโลไบต์


1
ทางออกที่ดี ฉันพบหนึ่งซับคุณคิดอย่างไร
brasofilo

2
@brasofilo ฉันคิดว่าหนึ่งซับถือว่าคุณมี 5MB แล้วลบจำนวนเงินที่ใช้
cdmckay

Ooook ยิงได้แน่นอน ปัญหาที่ฉันมีกับรหัสของคุณไม่สามารถรับผลลัพธ์ที่ถูกต้องด้วยวิธีที่ถูกต้องในการแปลงขนาดเป็น KB, MB, GB ใน Javascript ... ฉันจะแก้ไขในวันพรุ่งนี้ แต่ถ้าคุณสามารถดูได้ ชื่นชม
brasofilo

1
ปรับปรุงประสิทธิภาพและคุณภาพของคำตอบนี้ที่นี่
smnbbrv

มันเป็นปี 2020 และคำตอบนี้ใช้ได้ดีทั้งบนวานิลลา Chrome และ Firefox ใน Win10 โดยให้ขนาด = 5,000
A. Chiesa

34

ค้นหาความยาวสูงสุดของสตริงเดียวที่สามารถเก็บไว้ใน localStorage

ตัวอย่างนี้จะค้นหาความยาวสูงสุดของสตริงที่สามารถจัดเก็บในlocalStorageแต่ละโดเมน

//Clear localStorage
for (var item in localStorage) delete localStorage[item];

window.result = window.result || document.getElementById('result');

result.textContent = 'Test running…';

//Start test
//Defer running so DOM can be updated with "test running" message
setTimeout(function () {

    //Variables
    var low = 0,
        high = 2e9,
        half;

    //Two billion may be a little low as a starting point, so increase if necessary
    while (canStore(high)) high *= 2;


    //Keep refining until low and high are equal
    while (low !== high) {
        half = Math.floor((high - low) / 2 + low);

        //Check if we can't scale down any further
        if (low === half || high === half) {
            console.info(low, high, half);
            //Set low to the maximum possible amount that can be stored 
            low = canStore(high) ? high : low;
            high = low;
            break;
        }


        //Check if the maximum storage is no higher than half
        if (storageMaxBetween(low, half)) {
            high = half;
            //The only other possibility is that it's higher than half but not higher than "high"
        } else {
            low = half + 1;
        }

    }

    //Show the result we found!
    result.innerHTML = 'The maximum length of a string that can be stored in localStorage is <strong>' + low + '</strong> characters.';

    //Functions
    function canStore(strLen) {
        try {
            delete localStorage.foo;
            localStorage.foo = Array(strLen + 1).join('A');
            return true;
        } catch (ex) {
            return false;
        }
    }


    function storageMaxBetween(low, high) {
        return canStore(low) && !canStore(high);
    }

}, 0);
<h1>LocalStorage single value max length test</h1>

<div id='result'>Please enable JavaScript</div>

โปรดทราบว่าความยาวของสตริงมี จำกัด ใน JavaScript หากคุณต้องการดูจำนวนข้อมูลสูงสุดที่สามารถเก็บไว้ในlocalStorageเมื่อไม่ จำกัด เพียงสตริงเดียวคุณสามารถใช้รหัสในคำตอบนี้

แก้ไข:กองตัวอย่างไม่สนับสนุนlocalStorageดังนั้นนี่คือการเชื่อมโยงไปยัง JSFiddle

ผล

Chrome (45.0.2454.101): 5242878 ตัวอักษร
Firefox (40.0.1): 5242883 ตัวอักษร
Internet Explorer (11.0.9600.18036) :16386 122066 122070 ตัวละคร

ฉันได้รับผลลัพธ์ที่แตกต่างกันในการทำงานแต่ละครั้งใน Internet Explorer


1
ตลก แต่การทดสอบง่ายๆของคุณหยุดระบบที่ทรงพลังของฉันเมื่อฉันทดสอบในเบราว์เซอร์ Edge (บน Win 10) หลังจากใช้งาน ~ 1 นาที ดังนั้นฉันจึงไม่สามารถต่อท้ายข้อมูลใหม่กับผลลัพธ์ของคุณ))
vatavale

33

เบราว์เซอร์มือถือ:

Browser    | Chrome    | Android Browser    | Firefox     | iOS Safari
Version    | 40        | 4.3                | 34          | 6-8
Available  | 10MB      | 2MB                | 10MB        | 5MB

เบราว์เซอร์เดสก์ท็อป:

Browser    | Chrome   | Opera    | Firefox    | Safari      | IE
Version    | 40       | 27       | 34         | 6-8         | 9-11
Available  | 10MB     | 10MB     | 10MB       | 5MB         | 10MB

ลิงค์อ้างอิง


6
ตัวเลขมาจากไหน
MrD

23
@BehnamMohammadi คุณสามารถเพิ่มการอ้างอิงถึงตำแหน่งที่คุณได้รับจากสิ่งนี้เพื่อความสมบูรณ์
Chris Lang

1
และไม่มีการกรอกข้อมูลอ้างอิง แต่สำหรับลูกหลานตัวเลขเหล่านี้เปลี่ยนไปเล็กน้อย เราควรอัปเดตสิ่งนี้ให้กับเบราว์เซอร์ของคุณและข้อมูลปัจจุบัน
Malavos

3
@ChrisLang เพิ่มลิงก์
Behnam Mohammadi

1
@Malavos เพิ่มลิงก์
Behnam Mohammadi


13

คุณไม่ต้องการทำให้วัตถุขนาดใหญ่เป็นวัตถุในรายการ localStorage เดียว นั่นจะไม่มีประสิทธิภาพมาก - ทุกอย่างจะต้องมีการแยกวิเคราะห์และเข้ารหัสใหม่ทุกครั้งที่มีการเปลี่ยนแปลงรายละเอียดเล็กน้อย นอกจากนี้ JSON ไม่สามารถจัดการการอ้างอิงโยงหลายอย่างภายในโครงสร้างวัตถุและลบรายละเอียดมากมายเช่นตัวสร้างคุณสมบัติที่ไม่ใช่ตัวเลขของอาร์เรย์สิ่งที่อยู่ในรายการเบาบางเป็นต้น

คุณสามารถใช้Rhaboo แทนได้ มันเก็บวัตถุขนาดใหญ่โดยใช้รายการ localStorage จำนวนมากเพื่อให้คุณสามารถเปลี่ยนแปลงขนาดเล็กได้อย่างรวดเร็ว วัตถุที่ถูกกู้คืนเป็นสำเนาที่ถูกต้องมากขึ้นของวัตถุที่บันทึกไว้และ API นั้นเรียบง่ายอย่างไม่น่าเชื่อ เช่น:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');

BTW ฉันเขียนมัน


1
ขอบคุณมาร์ติน คุณอาจตรวจสอบ repo ของฉัน 'evon' เช่นกัน ตอนนี้เป็นซีเรียลไลเซอร์เท่านั้นและหมึกก็เปียกมาก แต่ก็เร็วกว่า rhaboo และอเนกประสงค์ ในไม่ช้า Rhaboo จะถูกแปลงเพื่อใช้ภายใน
เอเดรียพฤษภาคม

7
มีประโยชน์ แต่ฉันไม่คิดว่าสิ่งนี้จะตอบคำถามที่ว่า "LocalStorage ขนาดสูงสุดคืออะไร" คำตอบของคุณอาจได้รับการปรับปรุงโดยระบุว่าจะเกิดอะไรขึ้นเมื่อห้องสมุดนี้พยายามจัดเก็บบางสิ่งที่เกินขนาดที่ จำกัด และวิธีตอบสนอง
Chris Moschini

6

ฉันกำลังทำสิ่งต่อไปนี้:

getLocalStorageSizeLimit = function () {

    var maxLength = Math.pow(2,24);
    var preLength = 0;
    var hugeString = "0";
    var testString;
    var keyName = "testingLengthKey";

    //2^24 = 16777216 should be enough to all browsers
    testString = (new Array(Math.pow(2, 24))).join("X");

    while (maxLength !== preLength) {
        try  {
            localStorage.setItem(keyName, testString);

            preLength = testString.length;
            maxLength = Math.ceil(preLength + ((hugeString.length - preLength) / 2));

            testString = hugeString.substr(0, maxLength);
        } catch (e) {
            hugeString = testString;

            maxLength = Math.floor(testString.length - (testString.length - preLength) / 2);
            testString = hugeString.substr(0, maxLength);
        }
    }

    localStorage.removeItem(keyName);

    maxLength = JSON.stringify(this.storageObject).length + maxLength + keyName.length - 2;

    return maxLength;
};

5
Maroun Maroun: ตรวจสอบการโพสต์อีกครั้งผู้เขียนได้ให้รหัสเพื่อตรวจสอบขนาดสูงสุดของการจัดเก็บในท้องถิ่นโดยทางโปรแกรม นี่ดูเหมือนจะเป็นคำตอบที่ถูกต้องไม่ใช่คำถามอื่น
Arend

การใช้งานรหัสนี้จะพ่นข้อผิดพลาด "คำสั่งการส่งคืนที่ผิดกฎหมาย" ใน Chrome เมื่อถึงเวลาเขียน
DrewT

6

ฉันชอบคำตอบของ cdmckayแต่มันก็ดูไม่ดีเลยที่จะตรวจสอบขนาดตามเวลาจริง: มันช้าเกินไป (2 วินาทีสำหรับฉัน) นี่คือรุ่นที่ได้รับการปรับปรุงซึ่งเร็วกว่าและแม่นยำกว่ามากขึ้นพร้อมตัวเลือกในการเลือกว่าข้อผิดพลาดจะมีขนาดใหญ่เพียงใด (ค่าเริ่มต้น250,000ข้อผิดพลาดเล็ก ๆ คือ - ยิ่งการคำนวณนานขึ้น):

function getLocalStorageMaxSize(error) {
  if (localStorage) {
    var max = 10 * 1024 * 1024,
        i = 64,
        string1024 = '',
        string = '',
        // generate a random key
        testKey = 'size-test-' + Math.random().toString(),
        minimalFound = 0,
        error = error || 25e4;

    // fill a string with 1024 symbols / bytes    
    while (i--) string1024 += 1e16;

    i = max / 1024;

    // fill a string with 'max' amount of symbols / bytes    
    while (i--) string += string1024;

    i = max;

    // binary search implementation
    while (i > 1) {
      try {
        localStorage.setItem(testKey, string.substr(0, i));
        localStorage.removeItem(testKey);

        if (minimalFound < i - error) {
          minimalFound = i;
          i = i * 1.5;
        }
        else break;
      } catch (e) {
        localStorage.removeItem(testKey);
        i = minimalFound + (i - minimalFound) / 2;
      }
    }

    return minimalFound;
  }
}

ทดสอบ:

console.log(getLocalStorageMaxSize()); // takes .3s
console.log(getLocalStorageMaxSize(.1)); // takes 2s, but way more exact

สิ่งนี้ทำงานได้เร็วกว่ามากสำหรับข้อผิดพลาดมาตรฐาน นอกจากนี้ยังสามารถแม่นยำมากขึ้นเมื่อจำเป็น


6

ฉันย่อการทดสอบไบนารีลงในฟังก์ชันนี้ที่ฉันใช้:

function getStorageTotalSize(upperLimit/*in bytes*/) {
    var store = localStorage, testkey = "$_test"; // (NOTE: Test key is part of the storage!!! It should also be an even number of characters)
    var test = function (_size) { try { store.removeItem(testkey); store.setItem(testkey, new Array(_size + 1).join('0')); } catch (_ex) { return false; } return true; }
    var backup = {};
    for (var i = 0, n = store.length; i < n; ++i) backup[store.key(i)] = store.getItem(store.key(i));
    store.clear(); // (you could iterate over the items and backup first then restore later)
    var low = 0, high = 1, _upperLimit = (upperLimit || 1024 * 1024 * 1024) / 2, upperTest = true;
    while ((upperTest = test(high)) && high < _upperLimit) { low = high; high *= 2; }
    if (!upperTest) {
        var half = ~~((high - low + 1) / 2); // (~~ is a faster Math.floor())
        high -= half;
        while (half > 0) high += (half = ~~(half / 2)) * (test(high) ? 1 : -1);
        high = testkey.length + high;
    }
    if (high > _upperLimit) high = _upperLimit;
    store.removeItem(testkey);
    for (var p in backup) store.setItem(p, backup[p]);
    return high * 2; // (*2 because of Unicode storage)
}

นอกจากนี้ยังสำรองเนื้อหาก่อนการทดสอบจากนั้นเรียกคืนเนื้อหา

วิธีการทำงาน: มันเพิ่มขนาดเป็นสองเท่าจนกว่าจะถึงขีด จำกัด หรือการทดสอบล้มเหลว จากนั้นจัดเก็บครึ่งหนึ่งของระยะห่างระหว่างต่ำและสูงและลบ / เพิ่มครึ่งหนึ่งของแต่ละครั้ง (ลบความล้มเหลวและเพิ่มความสำเร็จ); สร้างเสริมคุณค่าที่เหมาะสม

upperLimitโดยค่าเริ่มต้นคือ 1GB และ จำกัด การสแกนแบบทวีคูณก่อนที่จะเริ่มการค้นหาแบบไบนารี่ ฉันสงสัยว่าสิ่งนี้จะต้องมีการเปลี่ยนแปลง แต่ฉันคิดอยู่เสมอ ;)

บน Chrome:

> getStorageTotalSize();
> 10485762
> 10485762/2
> 5242881
> localStorage.setItem("a", new Array(5242880).join("0")) // works
> localStorage.setItem("a", new Array(5242881).join("0")) // fails ('a' takes one spot [2 bytes])

IE11, Edge และ FireFox รายงานขนาดสูงสุดเท่ากัน (10485762 ไบต์)


1
(และอย่าลืมlocalStorage.Clear()ก่อนและหลังการทดสอบของคุณ
simonmysun

5

คุณสามารถใช้รหัสต่อไปนี้ในเบราว์เซอร์ที่ทันสมัยเพื่อตรวจสอบโควต้าการจัดเก็บ (ทั้งหมด & ใช้) อย่างมีประสิทธิภาพในเวลาจริง:

if ('storage' in navigator && 'estimate' in navigator.storage) {
        navigator.storage.estimate()
            .then(estimate => {
                console.log("Usage (in Bytes): ", estimate.usage,
                            ",  Total Quota (in Bytes): ", estimate.quota);
            });
}

ใช้งานไม่ได้กับ Chrome Usage (in Bytes): 647 , Total Quota (in Bytes): 32901464711 นั่นเป็นสิ่งที่ผิด: ขนาดโดยรวมที่เป็นไปได้คือ 10485762
James Wilkins

1

เมื่อฉันพัฒนาส่วนขยายChrome (เบราว์เซอร์เดสก์ท็อป) และทดสอบLocal Storageขนาดสูงสุดจริงด้วยเหตุนี้

ผลลัพธ์ของฉัน:

Ubuntu 18.04.1 LTS (64-bit)
Chrome 71.0.3578.98 (Official Build) (64-bit)
Local Storage content size 10240 KB (10 MB)

มากกว่า10240 KBการใช้งานทำให้ฉันเกิดข้อผิดพลาด:

Uncaught DOMException: ล้มเหลวในการเรียกใช้ 'setItem' บน 'Storage': การตั้งค่า 'notes' เกินโควต้า


0

ฉันเขียนรหัสง่ายๆที่ทดสอบขนาด localStorage เป็นไบต์

https://github.com/gkucmierz/Test-of-localStorage-limits-quota

const check = bytes => {
  try {
    localStorage.clear();
    localStorage.setItem('a', '0'.repeat(bytes));
    localStorage.clear();
    return true;
  } catch(e) {
    localStorage.clear();
    return false;
  }
};

หน้า Github:

https://gkucmierz.github.io/Test-of-localStorage-limits-quota/

ฉันมีผลลัพธ์เหมือนกันบนเดสก์ทอปโครเมี่ยม, โอเปร่า, Firefox, กล้าหาญและโครเมี่ยมมือถือซึ่งเป็น ~ 5Mbytes

ป้อนคำอธิบายรูปภาพที่นี่

และมีขนาดเล็กลงครึ่งหนึ่งเป็นซาฟารี ~ 2Mbytes

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.