4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[JavaScript] 動的にinput[type=file]を組み立てて画像をアップロードしたらBase64が手に入るコード

Last updated at Posted at 2020-03-27

画像アップロードする時に、以下のように display: none をつかってブラウザ本来の input[type=file] をみえないようにした上で独自レイアウトのボタンで画像アップロードするような実装を時々みかけます。

<label for="hoge">画像アップロード</label>
<input id="hoge" type="file" style="display: none">

で、 addEventListener でファイル変更検知を行ったりと。
けれど、上記のようにするとマークアップがある程度拘束されてしまいます。やりたいことはボタンをクリックしたら画像をアップロードしてBase64を手にいれるとかそういう話なので、クリックイベントを仕込んで以下のコードを実行すればOKです。

<div style="width: 0; height: 0; overflow: hidden;">
  <input id="browserPhotoUploader" type="file" accept="image/*" />
</div>
public getPictureFromBrowser() {
  /*
   * input[type=file] を組み立て
   */
  const inputFile: HTMLElement = document.querySelector('input#browserPhotoUploader');

  return new Promise(resolve => {
    /*
     * input[type=file] の変更(change)を検知したら、ファイルをアップロードしてresolveする
     */  
    inputFile.addEventListener(
        'change',
        (e) => {
          const file = e.target.files[0];
          const reader = new FileReader();

          reader.onload = (fileInput => {
            /*
             * アップロードされるファイルが画像かを簡易判定
             */  
            if (file.type.indexOf('image') < 0) {
              reject(null);
            }

            return (event) => {
              resolve(event.target.result);
            };
          })(file);

          reader.readAsDataURL(file);
        },
        false,
    );

    /*
     * input[type=file] をクリック
     * イベントリスナーよりあとに実行されるように
     */  
    inputFile.click();
  });
}

このコードだったらHTML側は

<button (click)="getPictureFromBrowser()">画像アップロード</button>

だけで済みますね。 display:none せずにすむのでシンプル!

それでは、また。

おまけ: TypeScript版

any 使ってるのちょっと何ですが・・・。

public getPictureFromBrowser(): Promise<string> {
    const inputFile: HTMLElement = document.querySelector('input#browserPhotoUploader');
    return new Promise(resolve => {
      inputFile.addEventListener(
        'change',
        (e: any) => {
          const file = e.target.files[0];
          const reader = new FileReader();

          reader.onload = (fileInput => {
            if (file.type.indexOf('image') < 0) {
              reject(null);
            }

            return (event) => {
              resolve(event.target.result);
            };
          })(file);

          reader.readAsDataURL(file);
        },
        false,
      );
      inputFile.click();
    });
  }
4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?