【JavaScript】<input type=”file”>にセットしたファイルをその場でブラウザのみでダウンロードできる様にする

 webページではファイルの送信のためにフォームの type=”file” の input タグを使うことが多いです。見た目の上では使っておらずとも入力欄では内部的にこれを持っていることが多いです。

<input type=”file”> – HTML: HyperText Markup Language | MDN

 この input[type=”file”] にファイルをセットした時、どのファイルがセットされているのか後から確認したいという要望が少なからずあります。ブラウザの素の機能でセットしたファイルの名前までは表示されるのですが、中身はわかりません。プレビューを表示できればよいのですが、システムの目的によっては画像やテキストファイルといったプレビューしやすいファイル以外も扱う時があります。限定的ならばなんやかんや何とかなりやすいのですが、なんでもアップロードできる場合は問題です。多様なファイル全てのランタイムをブラウザで実行するプログラムに含めるのは現実的ではありません。妥協案として使えるセットしたファイルをその場でダウンロードできる方法を紹介します。紹介する方法の特徴的な点はサーバーへのアップロードを行わない点にあります。この点により、高速でセキュアな簡易なプレビューを実現できます。

 実際のデモとコードが次です。

<div class="App">
  <input type="file" id="send-file" />
  <a id="for-preview"></a>
</div>
// ファイルが変更された時に実行される関数
const handleChange = (e) => {
  const reader = new FileReader();
  // FileReader からBase64形式の URL として使えるファイルの中身を取得
  // a タグの href にすることでファイルのダウンロードを実現する
  const previewEl = document.getElementById("for-preview");
  // @see https://developer.mozilla.org/ja/docs/Web/API/FileReader
  reader.addEventListener("load", () => (previewEl.href = reader.result));

  // ファイルを FileReader に渡す。
  const file = e.currentTarget.files[0];
  if (file) {
    / ダウンロードするファイルの名前とダウンロードリンクに表示される文字列をセットされたファイルの名前にする
    previewEl.download = file.name;
    previewEl.innerText = file.name;
    // @see https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsDataURL
    reader.readAsDataURL(file);
  }
};
document.getElementById("send-file").addEventListener("change", handleChange);
import "./styles.css";
import React from "react";

// React 版です

export default function App() {
  // fileの中身と名前を保持
  const [uri, setUri] = React.useState("");
  const [fileName, setFileName] = React.useState("");
  // ファイル変更あったら↑にセット
  const handleChange = (e) => {
    const reader = new FileReader();
    // @see https://developer.mozilla.org/ja/docs/Web/API/FileReader
    reader.addEventListener("load", () => setUri(reader.result));

    const file = e.currentTarget.files[0];
    if (file) {
      setFileName(file.name);
      // @see https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsDataURL
      reader.readAsDataURL(file);
    }
  };
  return (
    <div className="App">
      <input type="file" onChange={handleChange} />
      <a href={uri} download={fileName}>
        {fileName}
      </a>
    </div>
  );
}

 セットされたファイルに変更があったら、それを FileReader.readAsDateURL で中身を読み取り、Base64 として a 要素の href にセットしています。これの a 要素を img 要素に、 href を src に変えればそれでもう画像のプレビューと同じです。

FileReader.readAsDataURL() – Web API | MDN

 特別ライブラリを用いずともブラウザ標準の機能で比較的シンプルにまとまります。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG