エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

選択したファイルをプレビュー表示する

ファイルをアップロードするときに利用する input タグ <input type="file"> ですが、ファイルを選択した時点でブラウザ上で画像データを取得することできることを利用してプレビュー表示させる方法です。

過去に使ったことがあったんですが、件のコードにしか情報がなかったので、あらためてブログに記録です。

アイディアとしては、ファイルが選択されたときの change イベントの中で、選択されたファイルを FileReader で読み出し、最終的に Base64エンコードして img タグに放り込む、というものです。

readAsArrayBuffer 関数は非同期なので、完了時に呼び出されるハンドラ onload 内に読み出したデータの処理を記述しています。

データの変換がなかなかケイオスなので、もう少しどうにかならないかという思いがあるところ。

<!DOCTYPE html>
<html>
  <body>
    <div>
      <input type="file" id="file-input">
    </div>

    <div>
      <img id="preview-image">
    </div>

    <script>
      const fileInput = document.getElementById('file-input')
      const previewImage = document.getElementById('preview-image')

      fileInput.addEventListener('change', (event) => {
        const reader = new window.FileReader()
        const file = event.target.files[0]

        reader.onload = (readerEvent) => {
          const data = new Uint8Array(readerEvent.target.result)

          const chunkSize = 0x8000;
          const chars = [];
          for (let i = 0; i < data.length; i += chunkSize) {
            chars.push(String.fromCharCode.apply(null, data.subarray(i, i + chunkSize)));
          }
          const encodedData = window.btoa(chars.join(''))

          previewImage.src = `data:${file.type};base64,${encodedData}`
        };

        reader.readAsArrayBuffer(file)
      })
    </script>
  </body>
</html>