Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【HTML】Safariで<input type="file" />で二度同じファイルをアップロードしようとすると、二回目のonchangeが発火しない

メモ。

HTMLでファイルダイアログを開いて指定したファイルを操作するとき、
以下のように<input type="file" />にonchange属性をつけ、そこにイベントハンドラ関数を設定します。

HTML
<div ng-app="myApp">
  <div ng-controller="MyAppCtrl">
    <input type="file" onchange="onChange(this)"/>
  </div>
</div>
JavaScript
function onChange(e) {
  console.log(e.value);
}

codepen.io

通常であれば、ボタンクリック時にファイルダイアログが開き、
ファイルが選択された状態でダイアログの「OK」ボタンを押すとonchangeに渡した関数が実行されます。

しかしSafariの場合、ダイアログでファイルを選択->OKを押した後(onchangeの関数実行)、
再びダイアログを開いて同じファイル選択->OKを押した場合に、onchangeに渡した関数が実行されません。

対策

同じような問題に引っかかっている方の記事が見つかりました。

https://qiita.com/te20/items/00a72535163c6d632408qiita.com

一度アップロードしたコンテンツをクリアしてあげれば、問題は解消されるようです。

<div ng-app="myApp">
  <div ng-controller="MyAppCtrl">
    <input type="file" onchange="onChange(this) onclick="onClick(this)"/>
  </div>
</div>
JavaScript
function onChange(e) {
  console.log(e.value);
}

function onClick(e) {
    e.target.value = "";
}

具体的には、inputタグに対応するDOMが持つvalueプロパティを空文字にしてあげます。
このinputタグのDOMはイベントハンドラ関数の引数からtargetプロパティとして取得できます。