iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0
Build on AWS

從零到雲端:AWS 開發之路系列 第 26

Day26 文字與影像的結合 — Base64 儲存日記到 localStorage

  • 分享至 

  • xImage
  •  

HTML 結構說明

HTML 決定了整個頁面的骨架。
主要分成兩個部分:

  1. <main>:負責「上傳照片與寫日記」
  2. <div id="history">:顯示「過去的日記紀錄」
  • <input type="file">:讓使用者上傳圖片
  • <img id="photoPreview">:顯示預覽圖片(初始隱藏)
  • <textarea>:輸入文字心情
  • <button>:送出日記
  • <div id="history">:下面會動態生成歷史紀錄
<main>
  <h1>我的照片日記</h1>
  <p>上傳今天的回憶 💭</p>
  <input type="file" id="photoInput" accept="image/*">
  <img id="photoPreview" src="" style="display:none">
  <textarea id="diaryText" rows="3" placeholder="寫下你的心情..."></textarea>
  <button id="uploadBtn">💾 儲存日記</button>
</main>

<div id="history"></div>

JavaScript 主程式邏輯:互動核心

取得 DOM 元素

這幾行是基礎操作,用 document.getElementById() 取得 HTML 元素,後面操作會用到

const photoInput = document.getElementById('photoInput');
const photoPreview = document.getElementById('photoPreview');
const uploadBtn = document.getElementById('uploadBtn');
const diaryText = document.getElementById('diaryText');
const historyDiv = document.getElementById('history');

selectedFile 則是用來暫存使用者選的照片:

let selectedFile = null;

圖片預覽功能

當使用者選擇一張圖片時,我們要先在畫面上顯示出來,這就靠 FileReader

  • FileReader 是一個瀏覽器內建 API,可以讀取本地檔案內容
  • readAsDataURL() 會把圖片轉成 Base64 編碼字串
  • photoPreview.src = e.target.result :預覽圖片顯示

注意:這裡沒有直接上傳圖片,而是轉成 Base64,因為接下來會存進 localStorage

photoInput.addEventListener('change', e => {
  const file = e.target.files[0];
  if(file){
    selectedFile = file;
    const reader = new FileReader();
    reader.onload = function(e){
      photoPreview.src = e.target.result;
      photoPreview.style.display = 'block';
    }
    reader.readAsDataURL(file);
  }
});

儲存日記到 localStorage

這段是最關鍵的地方,實現了「無後端儲存」

uploadBtn.addEventListener('click', () => {
  if(!selectedFile){
    alert("📷 請先選擇照片!");
    return;
  }

  const diary = diaryText.value.trim();
  if(!diary){
    alert("✏️ 請輸入日記文字!");
    return;
  }

  const reader = new FileReader();
  reader.onload = function(e){
    const base64Image = e.target.result;

    const diaryEntry = {
      image: base64Image,
      text: diary,
      timestamp: new Date().toISOString()
    };

    const diaries = JSON.parse(localStorage.getItem('diaries') || '[]');
    diaries.unshift(diaryEntry);
    localStorage.setItem('diaries', JSON.stringify(diaries));

    photoPreview.src = '';
    photoPreview.style.display = 'none';
    photoInput.value = '';
    diaryText.value = '';

    renderDiaries();
  }
  reader.readAsDataURL(selectedFile);
});

我們分段看:

1. 輸入檢查:確認照片和文字都有選擇

FileReader 再次轉 Base64:把圖片轉成文字字串
建立一個日記物件:

{
  image: "data:image/jpeg;base64,...",
  text: "今天吃了很好吃的蛋糕",
  timestamp: "2025-10-09T05:00:00.000Z"
}

2. 寫進 localStorage:

step1: 用 localStorage.getItem() 取出原本的日記
step2: 用 JSON.parse() 轉成陣列
step3: 把新的日記放在最前面 unshift()
step4: 再存回去:localStorage.setItem()
localStorage 就像是瀏覽器內建的小型資料庫,可以儲存字串資料,永久存在(除非清除快取)

渲染歷史日記

儲存完後要即時更新畫面,顯示最新的日記
清空舊的內容 innerHTML = '',並從 localStorage 把資料取出,再用 JavaScript 動態建立每一張「卡片」,加進 <div id="history">

function renderDiaries(){
  historyDiv.innerHTML = '';
  const diaries = JSON.parse(localStorage.getItem('diaries') || '[]');
  diaries.forEach(diary => {
    const card = document.createElement('div');
    card.className = 'diary-card';

    const img = document.createElement('img');
    img.src = diary.image;
    card.appendChild(img);

    const textDiv = document.createElement('div');
    textDiv.className = 'diary-text';
    textDiv.textContent = diary.text;
    card.appendChild(textDiv);

    historyDiv.appendChild(card);
  });
}

在網頁載入時自動執行,這樣重新整理也能看到以前的內容

renderDiaries();

成果展示

日記在未輸入前的樣子:
https://ithelp.ithome.com.tw/upload/images/20251009/201692514HSj0rAREP.png
選擇照片與輸入文字並按送出:
https://ithelp.ithome.com.tw/upload/images/20251009/20169251FUTrdF8syP.png
日記呈現的樣子:
https://ithelp.ithome.com.tw/upload/images/20251009/201692510I4VQ2qYqE.png


上一篇
Day 25: 雲端收納 ─ Lambda 幫我把照片存進 S3
系列文
從零到雲端:AWS 開發之路26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言