DOBON.NET DOBON.NETプログラミング掲示板過去ログ

input-fileタグでアップロードする方法

環境/言語:[XP、C#、.NET Framework1.1]
分類:[ASP.NET]

"multipart/form-data"で、ファイルをアップロードしたいと考えています。
環境はIE限定。C#&ASPです。(開発環境はIE8、VS2003です)

とりあえず、

http://www.atmarkit.co.jp/fdotnet/dotnettips/321uploadform/uploadform.html

 ここを参考に、input type=fileタグを使い、実現しようと考えました。

 やりたい事は、

1.ファイルオープンダイアログでファイルを選択。
2.送信ボタンを押したらアップロード開始〜終了

 です。
 現在は、JavaScriptを使用せず、上記サイトのように、送信ボタンのClickイ
ベントで試してみてるのですが、送信ボタン押下の瞬間にinputタグのvalueが
消えてしまい、Clickイベントが発生しません。
 もう一度送信ボタンを押すとClickイベントは発生するのですが、当然valueが
ないので送信なんかできません。

 inputタグからrunat="server"を消せば、valueは消えないとの事ですが、server
サイドでは処理ができなくなってしまいます。
 ぶっちゃけ、上記サイトの処理って実現できなくて困っています。

 正直、どうやったらアップロードってできるんだろう…とか思えてます。
 inputタグ関連をいろいろ調べてみてたんですが、書いてある事はほとんど同じ
で、やれそうな事が書いてあるのに…。ie8のセキュリティ強化の問題でしょうか。

 業務アプリなので、「信頼済みサイト」にしても結果は同じでした。
 どなたか、

・inputタグで上記のような状況でハマった場合の対処方法
・inputタグが使えないなら、他の対処方法

 をご存知であれば、お教え願いたく思います。
おのでらです。

「value」ではなくリンク先ページにある「3. アップロードされたファイルの操作」の

Request.Files["userfile"];

の方法ではアップロードされたファイルを取得できなかったということでしょうか?
■No26376に返信(おのでらさんの記事)
> 「value」ではなくリンク先ページにある「3. アップロードされたファイルの操作」の
>
> Request.Files["userfile"];
>
> の方法ではアップロードされたファイルを取得できなかったということでしょうか?

 返信ありがとうございます。
 そちらもやってみましたが、Requestでは取得できませんでした…。
 というか、そもそもボタンを1回押した時、Clickイベントが発生していないのです。postbackも発生していません。そして、この1回目のボタン押下の時、どうもinputタグがクリアされているらしく、再度ボタンを押して、今度はClickイベントが発生しても、何も入っていないという状況です。

 inputタグにファイル名がある時、なぜClickイベントが発生しないか…。そこが(そこも)わかりません。
■No26377に返信(あきよしさんの記事)
> この1回目のボタン押下の時、どうもinputタグがクリアされているらしく、再度ボタンを押して、
> 今度はClickイベントが発生しても、何も入っていないという状況です。

input タグがクリアされるというのはどのようにして確認されるのでしょうか。
どのように記述されているのかお教えいただけるとありがたいです。

void Upload_Click(object sender, EventArgs e) {
    HttpPostedFile file1 = Request.Files["file1"];
    ...
}

<form id="form1" runat="server" enctype="multipart/form-data">
    <input type="file" name="file1" /><br />
    <input id="UploadButton" runat="server" type="button"
            value="Upload" onserverclick="Upload_Click" />
</form>
2010/02/04(Thu) 14:00:29 編集(投稿者)
2010/02/04(Thu) 14:00:25 編集(投稿者)

もりおさん、返事ありがとうございます。

全てサーバーサイドで確認しています。
Page_Loadイベントの先頭にブレイクポイントを置き、HttpPostedFileを宣言してpostファイル名を取得しました。(nullです。)
後は、もりおさんが記載されているソースの通りです。formタグにenctypeを設定し、Page_Loadイベント後に来るクリックイベントハンドラ

this.UploadButton.Click += new System.EventHandler(this.UploadButton_Click);

こんなのを宣言してます。
ちなみに、このイベントハンドラで定義したメソッドUploadButton_Click内は、returnのみを置いて、そこにブレイクポイントを置いています。
そのタイミングで、クイックウォッチでRequest.Files["file1"]を見ても、nullになります。まあ、file1にクライアントのファイル名が設定されている時、ボタンを押下してもこのブレイクポイントには到達しないので、到達する時は決まってfile1は空ですから、当然ですが。

あ。Page_Loadの先頭のブレイクポイントにも、file1に値設定時はとまりません。
イベントが発生していないとしか思えないです。

後、いろいろ調べてると、input-fileタグはいろいろと制約があり、特にie8からは制約が増えているようなんです。
まあ、制約が増えているにせよ、まったくアップロードができなくなっている訳はないですから、なんらかの方法があるとは思っているのですが…。権限の問題なのかなぁ…
■No26379に返信(あきよしさんの記事)

> そのタイミングで、クイックウォッチでRequest.Files["file1"]を見ても、nullになります。

input コントロールにてアップロードするファイルを選択しなかった場合 FileName プロ
パティが "" になるだけで HttpPostedFile オブジェクトは null にはならないはずで
す。
状況を再現したいので記述されているソースを丸ごとお教えいただくことは出来ないでし
ょうか。
■No26380に返信(もりおさんの記事)
> input コントロールにてアップロードするファイルを選択しなかった場合 FileName プロ
> パティが "" になるだけで HttpPostedFile オブジェクトは null にはならないはずで
> す。

 !!
 そうなんですか?
 それなら、何度か試しているうちに、取れてた事があったかもしれません。今ちょっとソースがむちゃくちゃになってて、自分でもちゃんと動かない事が判っているのです。
 それでも、ちょっと心当たりがありますので、試してみます。アドバイスありがとうございました。

(一時保留…)
■No26381に返信(あきよしさんの記事)
> ■No26380に返信(もりおさんの記事)
>>input コントロールにてアップロードするファイルを選択しなかった場合 FileName プロ
>>パティが "" になるだけで HttpPostedFile オブジェクトは null にはならないはずで
>>す。
>
>  !!
>  そうなんですか?
>  それなら、何度か試しているうちに、取れてた事があったかもしれません。今ちょっとソースがむちゃくちゃになってて、自分でもちゃんと動かない事が判っているのです。
>  それでも、ちょっと心当たりがありますので、試してみます。アドバイスありがとうございました。
>
> (一時保留…)

 ダメでした…。
 HttpPostedFileで取得したfile1のInputStream内に、なんか大量のデータが入っ
ていたので、もしかしてこれかと思ってたのですが、強引に

private void btnUpload_Click(object sender, System.EventArgs e)
{
HttpPostedFile posted = Request.Files["txtTempFile"];

string path = Server.MapPath("./");
posted.SaveAs(path + "test.txt");
return;
}

こうしてみても、出来たのは空のtest.txtでした。



ソースをさらしてみます。
ちなみに、フレーム使ってます。下記のformは、そのフレームウインドウの1つの中で完結しています。
【asp】
<form style="WIDTH: 982px" id="forTop" method="post" runat="server" autocomplete="off"
enctype="multipart/form-data">
(…省略…)
<asp:button id="btnUpload" style="Z-INDEX: 0" runat="server" Width="40px" Text="添付" ></asp:button>
(…省略…)
<INPUT id="txtTempFile" size="1" type="file" runat="server" name=txtTempFile>
(…省略…)
</form>

【c#】
#region -[Event] InitializeComponent : フォーム デザイナで生成されたコード
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.btnUpload.Click += new System.EventHandler(this.btnUpload_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion

private void btnUpload_Click(object sender, System.EventArgs e)
{
HttpPostedFile posted = Request.Files["txtTempFile"];

string path = Server.MapPath("./");
posted.SaveAs(path + "test.txt");
return;
}

 こんな感じでいいでしょうか。
 現象としては、txtTempFileの参照ボタン押下でダイアログ表示。ファイル選択で、txtTempFile
に値設定。
 btnUpload1回押下でtxtTempFileで消えてしまう。イベント発生せず。
 btnUpload2回目押下イベント発生。btnUpload_Clickが実行されるものの、postedはからっぽです。
■No26381に返信(あきよしさんの記事)

> string path = Server.MapPath("./");
> posted.SaveAs(path + "test.txt");

パスの結合は
string filePath = System.IO.Path.Combine(path, "test.txt");
posted.SaveAs(filePath);
を用いたほうが善いかと思います。

> <INPUT id="txtTempFile" size="1" type="file" runat="server" name=txtTempFile>

INPUT は小文字にして name 属性は " で囲ってタグは閉じたほうが善いかと思います。
<input id="txtTempFile" size="1" type="file" runat="server" name="txtTempFile" />


さて、困ったことに私の環境ではご掲示いただいたコードでうまく動きました。

> btnUpload1回押下でtxtTempFileで消えてしまう。イベント発生せず。

txtTempFile が消えてしまうというのはアップロードコントロールに表示された文字列が
消えてしまうということでしょうか。
そうしますと画面の書き換え自体は行われるみたいですね。
イベントが発生しないというのが気になります。
No26378 の最小限のコードでも同じようになりますでしょうか。
> No26378 の最小限のコードでも同じようになりますでしょうか。

 やってみました。動きます!
 ありがとうございます。これで原因が絞る事ができるかもしれません。
 解決したら、また報告します。
動きました。ありがとうございます。

問題となっていた箇所は、どうもここの模様です。

<asp:button id="btnUpload" style="Z-INDEX: 0" runat="server" Width="40px" Text="添付" ></asp:button>

aspのオブジェクトではなく、inputタグのボタンにしました。
<INPUT id="UploadButton" value="Upload" type="button" name="UploadButton" runat="server">
※タグが閉じてないのは、vs2003が勝手に消したから?だと思います。
 ちなみにINPUTが大文字なのも、VS2003のデザインビューアが勝手に変えてます…。html側で書いても、デザインビューアをあけたら書き換えてしまったり。

で、これで動いたのですが<input type=file>のスタイルをDISPLAY: noneで消したりすると「アクセスが拒否されました」とかで怒られます。そうやって利用しようと思ってたんですが…。ちょっと工夫が必要でしょうね。
うーん。でも、aspのボタンでも、もりおさんのは動いたんですよね…。
そこがちょっと腑に落ちませんが。とりあえず解決です。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板