จะบันทึกภาพไปยัง localStorage และแสดงในหน้าถัดไปได้อย่างไร?


154

ดังนั้นโดยทั่วไปฉันต้องอัปโหลดภาพเดียวบันทึกลงใน localStorage จากนั้นแสดงในหน้าถัดไป

ขณะนี้ฉันมีการอัปโหลดไฟล์ HTML ของฉัน:

<input type='file' id="uploadBannerImage" onchange="readURL(this);" />

ซึ่งใช้ฟังก์ชั่นนี้เพื่อแสดงภาพบนหน้า

function readURL(input) 
{
    document.getElementById("bannerImg").style.display = "block";

    if (input.files && input.files[0]) {
        var reader = new FileReader();

        reader.onload = function (e) {
            document.getElementById('bannerImg').src =  e.target.result;
        }

        reader.readAsDataURL(input.files[0]);
    }
}

ภาพจะปรากฏขึ้นทันทีบนหน้าเพื่อให้ผู้ใช้เห็น พวกเขาจะถูกขอให้กรอกแบบฟอร์มที่เหลือ ส่วนนี้ทำงานได้อย่างสมบูรณ์

เมื่อแบบฟอร์มเสร็จสมบูรณ์แล้วพวกเขาก็กดปุ่ม 'บันทึก' เมื่อกดปุ่มนี้ฉันจะบันทึกอินพุตแบบฟอร์มทั้งหมดเป็นlocalStorageสตริง ฉันต้องการวิธีในการบันทึกภาพเป็นlocalStorageรายการด้วย

ปุ่มบันทึกจะนำพวกเขาไปยังหน้าใหม่ หน้าใหม่นี้จะแสดงข้อมูลผู้ใช้ในตารางโดยมีรูปภาพอยู่ด้านบน

ดังนั้นธรรมดาและเรียบง่ายที่ฉันต้องการที่จะบันทึกภาพในlocalStorageครั้งเดียว 'บันทึก' localStorageกดปุ่มแล้วกู้ภาพในหน้าถัดไปจาก

ผมพบว่าการแก้ปัญหาบางอย่างเช่นไวโอลินนี้และบทความนี้ที่ moz: // Hacks

แม้ว่าฉันยังคงสับสนอย่างมากเกี่ยวกับวิธีการทำงานนี้และฉันต้องการเพียงวิธีแก้ปัญหาง่ายๆ โดยทั่วไปฉันแค่ต้องค้นหาภาพผ่านgetElementByIDเมื่อกดปุ่ม 'บันทึก' แล้วประมวลผลและบันทึกภาพ


2
เกิดอะไรขึ้นกับการจัดเก็บ reader.result ใน localstorage เช่นตัวอย่างนี้: jsfiddle.net/x11joex11/9g8NN ?
ติดตาม

สำหรับคนที่ต้องการเก็บข้อมูลจำนวนมากบน localStorage ไลบรารีนี้ค่อนข้างดี: pieroxy / lz-string: อัลกอริทึมการบีบอัดที่ใช้ LZ สำหรับ JavaScript
brasofilo

"ฉันต้องการโซลูชันที่เรียบง่าย" ทุกคนไม่ใช่เหรอ
Rodrigo

คำตอบ:


213

สำหรับผู้ที่ต้องการแก้ไขปัญหานี้ด้วย:

ประการแรกฉันคว้าภาพของฉันด้วยgetElementByIDและบันทึกภาพเป็น Base64 จากนั้นฉันบันทึกสตริง Base64 เป็นlocalStorageค่าของฉัน

bannerImage = document.getElementById('bannerImg');
imgData = getBase64Image(bannerImage);
localStorage.setItem("imgData", imgData);

นี่คือฟังก์ชั่นที่แปลงรูปภาพเป็นสตริง Base64:

function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

จากนั้นในหน้าถัดไปของฉันฉันสร้างภาพด้วยช่องว่างsrcดังนี้:

<img src="" id="tableBanner" />

และตรงไปตรงมาเมื่อเพจโหลดฉันใช้สามบรรทัดถัดไปเพื่อรับสตริง Base64 จากlocalStorageและนำไปใช้กับรูปภาพด้วยที่ว่างเปล่าที่srcฉันสร้าง:

var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;

ทดสอบในเบราว์เซอร์และรุ่นที่แตกต่างกันค่อนข้างมากและดูเหมือนว่าจะทำงานได้ค่อนข้างดี


1
ไม่รองรับ Gif เนื่องจากผ้าใบไม่รองรับ gif
อัลเลน

16
คุณไม่ต้องการฟังก์ชัน getBase64Image URL ข้อมูลเป็นฐาน 64 อยู่แล้วดังนั้นเมื่อคุณเรียกใช้ reader.readAsDataURL e.target.result ที่ส่งไปยัง reader.onload handler จะเป็นสิ่งที่คุณต้องการ
James H. Kelly

3
โปรดจำไว้ว่ามีขีด จำกัด ประมาณ 5MB สำหรับการจัดเก็บในพื้นที่ / เซสชัน และการแปลงอิมเมจไบนารีเป็นสตริงที่เข้ารหัส 64 เบสจะทำให้มีขนาดใหญ่ขึ้นประมาณ 30% ดังนั้นนี่จะไม่ทำงานกับภาพความละเอียดสูง
Noel Abrahams

เหตุใดคุณจึงตัดส่วนเริ่มต้นของ URL ข้อมูล เพื่อลดขนาด?
deostroll

3
โปรดทราบว่าคุณต้องโหลดรูปภาพให้เต็มก่อน (มิฉะนั้นจะทำให้ภาพว่าง) ดังนั้นในบางกรณีคุณต้องห่อการจัดการ: bannerImage.addEventListener ("load", function () {});
YE

9

ฉันเขียนไลบรารี่ขนาด 2,2kb ของการบันทึกภาพใน localStorage JQueryImageCaching การใช้งาน:

<img data-src="path/to/image">
<script>
    $('img').imageCaching();
</script>

2
2.2 กิโลไบต์มีขนาดใหญ่มากสำหรับบางสิ่งเช่นนี้บวกกับการคาดเดาที่ไม่ได้คำนึงถึงขนาดของขนาดของ jQuery ฉันอยากจะแนะนำให้เขียนมันโดยไม่ใช้ jQuery บางทีมันอาจจะเล็กกว่านี้
ChrisBrownie55

1.74 KB อ้างอิงจาก gitbub
hakiko

6

คุณสามารถทำให้ภาพเป็นอนุกรมใน Data URI มีบทช่วยสอนในโพสต์บล็อกนี้ นั่นจะสร้างสตริงที่คุณสามารถเก็บไว้ในที่จัดเก็บในตัวเครื่อง จากนั้นในหน้าถัดไปให้ใช้ data uri เป็นแหล่งที่มาของภาพ


0

"โปรดทราบว่าคุณต้องโหลดอิมเมจให้เต็มก่อน (ไม่เช่นนั้นจะมีอิมเมจที่ว่างเปล่า) ดังนั้นในบางกรณีคุณต้องห่อการจัดการ: bannerImage.addEventListener (" load ", function () {}); - ยูกะ 1 พ.ย. 17 เวลา 13:04 น. "

นี่เป็นสิ่งสำคัญอย่างยิ่ง หนึ่งในตัวเลือกที่ฉันกำลังสำรวจช่วงบ่ายนี้คือการใช้วิธีการโทรกลับด้วยจาวาสคริปต์แทนที่จะใช้ addEventListeners เนื่องจากดูเหมือนว่าจะไม่สามารถผูกได้อย่างถูกต้อง เตรียมองค์ประกอบทั้งหมดให้พร้อมก่อนโหลดหน้าเว็บโดยไม่ต้องรีเฟรชหน้า

หากใครสามารถขยายได้โปรดทำตามที่คุณใช้ในการตั้งค่าการรอคอยการติดต่อกลับหรือวิธีการ addEventListener เพื่อให้ได้ผลลัพธ์ที่ต้องการ ตัวไหนและทำไม


ใช้การโทรกลับทุกครั้งหากทำได้และไม่ควรใช้การตั้งเวลาออกหากคุณสามารถหลีกเลี่ยงได้ โดยการออกแบบคุณต้องการให้สิ่งนั้นเกิดขึ้นหลังจากสิ่งที่ผ่านมาโดยมีค่าใช้จ่ายน้อยที่สุด นี่คือสิ่งที่การเรียกกลับได้รับการออกแบบสำหรับ
Grayson

-2

ฉันเกิดปัญหาเดียวกันขึ้นมาแทนที่จะเก็บภาพซึ่งในที่สุดก็ล้นหน่วยความจำภายในคุณเพียงแค่เก็บเส้นทางไปยังภาพ สิ่งที่ต้องการ:

let imagen = ev.target.getAttribute('src');
arrayImagenes.push(imagen);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.