Closed10

【JavaScript】Fileを扱えるようになりたいんだ

じょーだんじょーだん

以下のコードを書いてみた。

import React from "react";

const index = () => {
  return (
    <>
      <h1>index</h1>
      <div>
        <form>
          <input type="file" onChange={(e) => console.log(e.target.files)} />
        </form>
      </div>
    </>
  );
};

export default index;

実行結果は以下のようになる。

FileListオブジェクトを取得できた。Fileオブジェクトを格納している。

このFileListオブジェクトは、<input>要素でtype=fileとしたときに返される。

例えばinputタグに multipleを指定した場合、複数のファイルを扱うことができる。
その場合以下のようになる。
2つのFileオブジェクトがFileListオブジェクトに格納されている。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/file
https://developer.mozilla.org/ja/docs/Web/API/FileList

じょーだんじょーだん

Fileって?

https://developer.mozilla.org/ja/docs/Web/API/File
によると、

ファイルについての情報を提供したり、ウェブページ内の JavaScript からその内容にアクセスできるようにしたりします。

とありました。
納得。例えばFileオブジェクトのtypeプロパティを見てみると"image/jpeg"とあり、画像ファイルに関する拡張子の情報を取得することができています。

じょーだんじょーだん

ドキュメントに以下のような記述が。

File オブジェクトは特別な種類の Blob オブジェクト

Blobオブジェクトを拡張することによって、Fileオブジェクトが作られています。

BlobオブジェクトとFileオブジェクトの違いについて、以下のqiita記事が分かりやすかったです。
https://qiita.com/yokra9/items/a629f416caf044d4a5db

じょーだんじょーだん

できた。
画像データを選択すると、画像が表示される。

import React, { ChangeEvent, useEffect, useState } from "react";

const index = () => {
  const [fileData, setFileData] = useState<File | undefined>(undefined);
  const [imageUrl, setImageUrl] = useState<string | undefined>(undefined);

  useEffect(() => {
    if (typeof fileData === "object") {
      setImageUrl(URL.createObjectURL(fileData));
    } else {
      setImageUrl(undefined);
    }
  }, [fileData]);
  return (
    <>
      <h1>index</h1>
      <div>
        <form>
          <input
            type="file"
            onChange={(e: ChangeEvent<HTMLInputElement>) => {
              e.target.files &&
                e.target.files[0] &&
                setFileData(e.target.files[0]);
            }}
          />
        </form>
      </div>
      <div>
        {imageUrl && (
          <img src={imageUrl} alt="プレビュー画像" style={{ width: "300px" }} />
        )}
      </div>
    </>
  );
};

export default index;
じょーだんじょーだん

https://developer.mozilla.org/ja/docs/Web/API/URL/revokeObjectURL

URL.revokeObjectURL() 静的メソッドは、以前に URL.createObjectURL() を呼び出して生成された既存のオブジェクト URL を解放します。 オブジェクト URL を使い終わったら、このメソッドを呼び出して、ファイルへの参照をこれ以上保持しないようにブラウザーに知らせます。

以下の例で作ったプログラムを改善する。
画像を変えたときに、変える前に表示するために使用していたオブジェクトURLを解放する。
https://zenn.dev/link/comments/f4be0b2892b4f7

じょーだんじょーだん
import React, { ChangeEvent, useEffect, useState } from "react";

const index = () => {
  const [fileData, setFileData] = useState<File | undefined>(undefined);
  const [imageUrl, setImageUrl] = useState<string | undefined>(undefined);

  useEffect(() => {
    if (typeof fileData === "object") {
+      imageUrl && URL.revokeObjectURL(imageUrl);
      setImageUrl(URL.createObjectURL(fileData));
    } else {
      setImageUrl(undefined);
    }
  }, [fileData]);
  return (
    <>
      <h1>index</h1>
      <div>
        <form>
          <input
            type="file"
            onChange={(e: ChangeEvent<HTMLInputElement>) => {
              e.target.files &&
                e.target.files[0] &&
                setFileData(e.target.files[0]);
            }}
          />
        </form>
      </div>
      <div>
        {imageUrl && (
          <img src={imageUrl} alt="プレビュー画像" style={{ width: "300px" }} />
        )}
      </div>
    </>
  );
};

export default index;
このスクラップは2023/10/09にクローズされました