HTML+JavaScriptでBasicなファイルのエクスポートとインポート

HTMLとJavaScriptを用いてファイルのエクスポート・インポートを実装する際のBasicな記述です。
以下を想定してみます。

  • ファイル形式:json
  • エクスポート:ファイルとしてローカルに保存するまで
  • インポート:ローカルに保存された単一ファイルを読み込み、JavaScript内部で読み取れる状態になるまで
  • 動作確認ブラウザ:
    • Google Chrome
    • Microsoft Edge (Chromium)
    • Mozilla Firefox
    • Safari (macOS)
    • Safari (iOS)
    • Safari (iPadOS)

エクスポート処理

まずはボタンを用意します。

<button id="export" aria-label="export">エクスポート</button>

基本的な処理が以下です。

/**
 * export処理
 */
const exportData = () => {
  // 適当なデータ
  const data = {
    name: 'Taro',
    age: 28
  }

  const json = JSON.stringify(data, null, ' ')
  const blob = new Blob([json], { type: 'application/json' })
  const url = URL.createObjectURL(blob)

  const linkTag = document.createElement('a')
  linkTag.href = url
  linkTag.download = 'export-data.json'
  linkTag.click()

  URL.revokeObjectURL(url)
  linkTag.remove()
}

const btn = document.querySelector('#export')
btn.addEventListener('click', exportData, false)

ポイントは以下になります。

  • dataJSON.stringifyで文字列に変換
  • JSON.stringifyの第三引数はインデントを指定できます(エクスポートしたファイルはエディターなどで編集される可能性を考えてスペース1つ分のインデントを指定)
  • new Blob()でBlobオブジェクトを生成
  • URL.createObjectURLでBlobオブジェクトのURLを生成
  • 生成したaノードにオブジェクトのURLをセットしダウンロード
  • URL.revokeObjectURLで、URL.createObjectURLで生成したURLを解放
  • 最後に生成したaノードを削除

インポート処理

まずは<input type="file">タグを用い、ファイルの選択手段を用意します。

<label id="import" for="file-upload" aria-label="import">
  <span>インポート</span>
  <input id="file-upload" type="file" style="display: none;">
</label>

基本的な処理が以下です。

/**
 * import処理
 * @param {object} e
 */
const importData = e => {
  const result = JSON.parse(e.target.result)

  // 別途バリデーション用意し通す
  const valid = validate(result)

  if(!valid) {
    return false
  }

  console.log(result)
}

// readerを用意しonloadイベントにimportData指定
const reader = new FileReader()
reader.onload = importData

const fileSelector = document.querySelector('#import')
const fileUploadInput = document.querySelector('#file-upload')

fileSelector.addEventListener('change', e => {
  const file = e.target.files[0]
  fileUploadInput.value = '' // 同名ファイルの読み込み時にイベント発火が出来ないのでクリア

  if (!file) {
    return false
  }

  if (file.type !== 'application/json') {
    return false
  }

  reader.readAsText(file)
}, false)

ポイントは以下になります。

  • new FileReader()でFileReaderを生成
  • readerのonloadにインポートを行う処理(上記だとimportData)を指定
  • ファイル選択時、同名ファイルの読み込み時にイベント発火が出来なくなるのを防ぐためfileUploadInput.value = ''でクリア
  • reader.readAsText()Fileの内容を文字列として格納
  • 格納した文字列をJSON.parseでパース
  • 必要に応じてバリデーション等を行う
ホームへ戻る