- PR -

WebDAVサーバに対する大きなファイルのアップロード

1
投稿者投稿内容
けーすけ
会議室デビュー日: 2003/01/02
投稿数: 4
投稿日時: 2006-01-11 19:24
【 やりたいこと(実現したいこと) 】
WebDAVサーバに対して、ファイルのアップロード/ダウンロードを
実現したいと思っています。

【 動作環境(WebDAVサーバ) 】
OS:Windows Server 2003 Standard Edition
HTTPサーバ:Internet Information Service

【 動作環境(クライアント) 】
OS:Windows XP Professional (SP2)
開発言語:Visual Studio .NET 2003 C#

【 問題点と状況 】
HttpWebRequestを使用して、ファイルをアップロードするロジックを
作成しました。基本的に問題なく動作しています。

大きなサイズ(900MByte)のファイルにて試したところ、
500MByteくらいを送信し終わったタイミングで、
例外エラー(OutOfMemory)が発生してプログラムが落ちました。

【 試したこと(状況) 】

(1) [HttpWebRequest]クラスの[AllowWriteStreamBuffering]プロパティに
[false]を設定して、バッファリングを無効にしてみました。

(2) 以下のようなエラー・メッセージが表示されました。

「この要求には、認証または正しいリダイレクトのためのデータのバッファが必要です。」

(3) [HttpWebRequest]クラスの[Credentials]プロパティに認証情報を
設定していたロジックをコメントアウトしてみました。

(4) 大きなサイズ(900MByte)のファイルを送信できましたが、
認証処理が実現できなくなってしまいました。

【 聞きたいこと(知りたいこと) 】

認証処理を実現した上で、大きなサイズ(900MByte)のファイルを
アップロードしたいのですが、何か良い対応方法はないでしょうか?

アップロードできるファイルサイズにリミット値があるのでしょうか?


【 作成したロジック 】

コード:
#!/usr/bin/perl


private void btnUpload_Click(object sender, System.EventArgs e)
{
HttpWebRequest request; // HttpWebRequest オブジェクト
HttpWebResponse response; // HttpWebResponse オブジェクト
NetworkCredential netCred; // 認証方式
FileStream inputStream; // 入力ファイル(クライアント側)
Stream outputStream; // 出力ファイル(WebDAVサーバ側)
long FileLength; // ファイル・サイズ
long SendLength; // 送信サイズ
long SendCnt; // 送信回数

if (!File.Exists(txtUploadFile.Text)) {
MessageBox.Show("指定されたクライアント側のファイルが存在しません。",
btnUpload.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}

this.Enabled = false; // フォームを無効にしてボタンを押せないようにする
Cursor.Current = Cursors.WaitCursor; // カーソルを待機カーソルに変更

// ファイルI/O用オブジェクトの作成
inputStream = new FileStream(txtUploadFile.Text, FileMode.Open);
FileLength = inputStream.Length;

// HttpRequestの作成
request = (HttpWebRequest)WebRequest.Create(txtPathWebDAV.Text +
Path.GetFileName(txtUploadFile.Text));

// 認証方式の初期化
netCred = new NetworkCredential("XXXXX", "XXXXX", "XXXXX");
request.Credentials = netCred;

// 10秒でタイムアウトさせる
request.Timeout = 10000;
request.Method = "PUT";
request.ContentLength = FileLength;
// request.AllowWriteStreamBuffering = false;

//バイト配列の作成
byte[] bytBuff = new Byte[ checked((uint)Math.Min(4096, FileLength))];

try
{
// リクエストデータを書込む為のストリームを作成
outputStream = request.GetRequestStream();

//読込み位置の初期化
int bytesRead = 0;

for (SendCnt = 1, SendLength = 0; SendLength < FileLength; SendCnt++)
{

// ストリームへの書込み
bytesRead = inputStream.Read( bytBuff, 0, bytBuff.Length);
if ( 0 == bytesRead ) continue;
outputStream.Write( bytBuff, 0 , bytesRead );
// outputStream.Flush();
SendLength += bytesRead;

// ステータスを表示する
lblUploadStatus.Text =
String.Format("送信回数:{0}、送信サイズ:{1}", SendCnt, SendLength);

// メッセージ・キューにあるWindowsメッセージをすべて処理する。
// 「応答なし」を回避する。
Application.DoEvents();
// GC.Collect();
// System.Threading.Thread.Sleep(50);

}

//レスポンスのチェック
using(response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.Created)
{
throw new Exception("ファイルが作成されませんでした。");
}
inputStream.Close();
response.Close();
}
}
catch(WebException err)
{
MessageBox.Show(err.Message.ToString(), "test", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Cursor.Current = Cursors.Default; // カーソルを元に戻す
this.Enabled = true; // フォームを有効に戻す

}





[ メッセージ編集済み 編集者: けーすけ 編集日時 2006-01-13 17:12 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-01-11 19:50
引用:

けーすけさんの書き込み (2006-01-11 19:24) より:

大きなサイズ(900MByte)のファイルにて試したところ、
500MByteくらいを送信し終わったタイミングで、
例外エラー(OutOfMemory)が発生してプログラムが落ちました。


これは、本当にメモリが不足してるんですね。

引用:

アップロードできるファイルサイズにリミット値があるのでしょうか?


こういう情報しか聞いたことがないですね。

  IISのWebDAVサービスでサイズの大きなファイル(48K)が413エラーになる

引用:

  Application.DoEvents();
// GC.Collect();
// System.Threading.Thread.Sleep(50);


色々回収しようと頑張ってるみたいですが、追いついていないんでしょうか...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
けーすけ
会議室デビュー日: 2003/01/02
投稿数: 4
投稿日時: 2006-01-12 23:12
【 状況報告 】

・WebDAVサーバに対する大きなファイルのアップロード
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=27405&forum=7

教えて頂いたサイトを参照して、[UploadReadAheadSize]の値を設定しました。
[UploadReadAheadSize]には、最大値(&HFFFFFFFF=4294967295、4 GB)を設定しました。

確認した手順とその結果は、以下の通りです。

(1) 仮想ディレクトリ[/lm/w3svc/1/root/webdav]の設定に[UploadReadAheadSize]を追加した。

@ メタベースの該当箇所をエクスポートした。

>iiscnfg /export /f d:\keisuke\ex.xml /sp /lm/w3svc/1/root/webdav
サーバーに接続中...完了。
Configuration exported from /lm/w3svc/1/root/webdav to file d:\keisuke\ex.xml.

A 出力された[ex.xml]ファイルに以下の行を追加した。

UploadReadAheadSize="4294967295"

B メタベースの該当箇所をインポートした。

>iiscnfg /import /f d:\keisuke\ex.xml /sp /lm/w3svc/1/root/webdav /dp /lm/w3svc/1/root/webdav
サーバーに接続中...完了。
Configuration imported from /lm/w3svc/1/root/webdav in file
d:\keisuke\ex.xml to /lm/w3svc/1/root/webdav in the Metabase.

C 念のためPCを再起動して、動作確認を行ったが、結果は同じだった。

500MByteくらいを送信し終わったタイミングで、
例外エラー(OutOfMemory)が発生してプログラムが落ちました。

(2) 仮想ディレクトリ[/lm/w3svc/1/root/webdav]の設定に[UploadReadAheadSize]を追加した。

@ メタベースの該当箇所をエクスポートした。

>iiscnfg /export /f d:\keisuke\ex.xml /sp /lm/w3svc/1/root
サーバーに接続中...完了。
Configuration exported from /lm/w3svc/1/root to file d:\keisuke\ex.xml.

A 出力された[ex.xml]ファイルに以下の行を追加した。

UploadReadAheadSize="4294967295"

B メタベースの該当箇所をインポートした。

>iiscnfg /import /f d:\keisuke\ex.xml /sp /lm/w3svc/1/root /dp /lm/w3svc/1/root
サーバーに接続中...完了。
Configuration imported from /lm/w3svc/1/root in file
d:\keisuke\ex.xml to /lm/w3svc/1/root in the Metabase.

C 念のためPCを再起動して、動作確認を行ったが、結果は同じだった。

500MByteくらいを送信し終わったタイミングで、
例外エラー(OutOfMemory)が発生してプログラムが落ちました。


報告が遅くなりましたが結局、解決できませんでした(状況は変わりませんでした)。

> これは、本当にメモリが不足してるんですね。

う〜ん。。。本当にメモリが不足してるようには見えません。
試しにWebDAVサーバとクライアントをスペック(メモリ・サイズ)の違うPCに
変えてみても、ちょうど同じサイズ(500MByteくらい)を送信し終わったタイミングで、
例外エラー(OutOfMemory)が発生してプログラムが落ちました。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-01-13 01:36
こちらで、まともな回答がついてますね。(^^;)
http://www.gdncom.jp/general/bbs/ShowPost.aspx?PostID=40689

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
けーすけ
会議室デビュー日: 2003/01/02
投稿数: 4
投稿日時: 2006-01-13 15:57
上記サイトで[Lady.BUG]さんから教えて頂いた通りのやり方で動作しました。

昨日は、うまく動作しなかったのですが。。。3、4回は試したと思います。
「認証するにはデータのバッファが必要です。」的なメッセージが表示されたと記憶しています。

ところが今日確認したら、何の問題もなく動作しました。
念の為、5回ほど試しましたが正常にアップロードが完了しました。

どうもありがとうございました。m(._.)m
けーすけ
会議室デビュー日: 2003/01/02
投稿数: 4
投稿日時: 2006-01-13 16:47
度々すみません。やはり正常に動作しませんでした。
WebDAVサーバ側のセキュリティ設定(認証設定)をいつの間にか外していたようです。


[Lady.BUG]さんに言われた通り、以下の2行を追加しました。

 request.AllowWriteStreamBuffering = false;
 request.PreAuthenticate = true;

そうすると、以下の行を実行する時に例外エラーが発生してしまいます。

// リクエストデータを書込む為のストリームを作成
outputStream = request.GetRequestStream();

エラーメッセージの内容は、以下の通りです。

「この要求には、認証または正しいリダイレクトのためのデータのバッファが必要です。」

何度もすみません。対応方法が分かる方がいれば、よろしくお願いします。
実行モジュールで使用できるヒープ領域やスタックサイズに制限があるのでしょうか?

1

スキルアップ/キャリアアップ(JOB@IT)