読者です 読者をやめる 読者になる 読者になる

業務系Webアプリでファイルアップロード後にローカルファイルを削除する

JavaScript HTML

とか「ええええーーー!」な仕様も、IE (ないしIEコンポーネントを使用したアプリ) & ActiveX & FileSystemオブジェクトで実現できてしまう。さすがはM$

ちなみに、この実現方法を思いつかせるインスピレーションを与えてくれたエントリはこちら↓
http://d.hatena.ne.jp/taka_2/20080306#p1

セキュリティの設定に穴をあける

WindowsXP SP2以前のスクリプトウィルスの大流行で判るとおり、Webで安全ではないActiveX(特にFileSystemオブジェクト)が利用できるとセキュリティホールになりえます。FileSystemオブジェクトの場合はデータ消失やデータ流出のリスクがあります。
故に、安全でないActiveXの実行許可は必要最低限のサイトに抑える必要があります。業務系WebアプリではHTTPサーバはプライベートIPで通信できるでしょうから、そのプライベートIPアドレスのみ許可するのが妥当でしょう。プライベートIPアドレスに限定することで外部からの攻撃に利用されることを未然に防ぎます。
気が向いたら設定方法についてエントリ書きます。

ファイルをアップロードする

クラシックASPではBASP21を利用して実現できます。ASP.NETはぐぐればいっぱい例があるでしょう。今回のお話はクライアント側のJavaScriptのお話なので、サーバ側はPerlC/C++で書いたCGIでもPHPでもJavaでも大丈夫です。
どのプラットフォームで実装するにしてもHTMLのフォームに必ず指定する記述があります。詳しくは下記エントリ参照。
http://d.hatena.ne.jp/babydaemons/20080520/1211278047

アップロードされたフォームデータから得られたクライアントPCのローカルファイル名は、処理完了後のファイル削除のときに必要ですから、セッション変数なりhiddenタグなりDBなりで記憶しておく必要があります。

ちなみにファイル削除のタイミングは、アップロード完了時点ではなく、そのデータを使った処理が完了した時点が親切でしょう。ユーザが処理をキャンセルしたり、サーバのスクリプトがバグってて落ちることも想定しましょう。

ファイルを削除する

いちおう、これだけ書けば目的のファイルは削除できます。

var fso = new ActiveXObject("Scripting.FileSystemObject");

if (fso.FileExists(file)) {
	fso.DeleteFile(file, true);
}

しかし、あらかじめクライアントPCのセキュリティ設定で穴をあけてないとJavaScriptエラーになりますし、そもそもIEで無ければActiveXObjectすらありません。現実的には、下記のチェックが必要になるでしょう。

  • ブラウザはIEか?
  • (クライアントのIPアドレスでチェックするなどして、)安全でないActiveXの実行が許可されているか?

私が実装したときは、IEコンポーネント利用の専用アプリだったので前者のチェックは省略しましたw
#だって、デスマって来てるし。orz

後者のチェックは本番環境にデプロイして足りないことに気づいてあわてて実装。
#あまり、クラシックASPでデプロイって言わないよねw