10

クライアントマシンからサーバーにファイルをチャンクでアップロードするモジュールを実装しています。サーバー側では、WCF Soap サービスを使用しています。

ファイルをチャンクでアップロードするために、Microsoft http://msdn.microsoft.com/en-us/library/aa717050.aspxからこのサンプルを実装しました。簡単なシナリオで動作させることができたので、ファイルをチャンクでアップロードします。このチャンク モジュールは、WSDualHttpBinding を使用しています。

特定のファイルのアップロード中にアップロード プロセスが何らかの理由 (ユーザーの選択、マシンの電源がオフになっているなど) で停止した場合に備えて、ファイルを再アップロードする機能を実装する必要があります。

私の WCF サービスには、サーバー側でファイルの書き込みを処理するメソッドがあります。

public void UploadFile(RemoteFileInfo request)
{
FileInfo fi = new FileInfo(Path.Combine(Utils.StorePath(), request.FileName));

if (!fi.Directory.Exists)
{
    fi.Directory.Create();
}

FileStream file = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write);
int count;
byte[] buffer = new byte[4096];
while ((count = request.FileByteStream.Read(buffer, 0, buffer.Length)) > 0)
{
    file.Write(buffer, 0, count);
    file.Flush();
}
request.FileByteStream.Close();
file.Position = 0;
file.Close();

if (request.FileByteStream != null)
{
    request.FileByteStream.Close();
    request.FileByteStream.Dispose();
}
}

チャンキング モジュールは、関数 request.FileByteStream.Read(buffer, 0, buffer.Length) が消費されている間にチャンクを送信しています。

ファイルストリームが初期化された後、ファイルはロックされます (これは、ファイルストリームを書き込み用に初期化するときの通常の動作です)。しかし、問題は、送受信プロセスの実行中にアップロードプロセスを停止してから、チャネルチャンキング モジュールによって使用されるデータはキャンセルされないため、WCF サービスはさらにデータが送信されるのを待っているため、送信タイムアウトが期限切れになるまでファイルはロックされたままになります (ファイル +2.5GB をアップロードする必要があるため、タイムアウトは 1 時間です)。次回のアップロード時に同じファイルをアップロードしようとすると、同じファイルのファイル ストリームを再度初期化できないため、WCF サービスで例外が発生します。

ファイルロックを回避/削除する方法があるかどうかを知りたいので、次回の実行時に、前のファイルストリームが既にファイルをロックしている場合でも、同じファイルを再アップロードできます。

どんな助けでも感謝します、ありがとう。

4

1 に答える 1

1

私は個人的にこの種のソリューションが好きではありません。接続を維持することは理想的ではありません。

あなたの例を使用すると、2.5GB ファイルの途中でプロセスが中止される可能性があります。上記の状況に陥ります。さらに悪いことに、すでに提出されたすべてのデータを再提出する必要があります。

私は自分でブロックを処理し、それらを同じファイルサーバー側に追加するというルートに行きます. ファイルの開始を示す WCF メソッドを呼び出し、データをブロック単位でアップロードしてから、アップロードが完了したら別のメソッドを呼び出します。ファイル名が一意であると確信している場合は、1 回のメソッド呼び出しでこれを達成することもできます。

何かのようなもの:

ulong StartFile(string filename) // This returns the data already uploaded
void UploadFile(string filename, ulong start, byte[] data)
void EndFile(string filename) // Just as a safety net

上記で概説したルートに行きたくない場合(質問に直接答えることはありません)、上記の問題に対する簡単な解決策は、アップロード中に一時ファイル名を使用し、ファイルの名前を一度変更することです。アップロードが完了しました。とにかく、アップロードが完了する前にサーバー上のアプリケーションがファイルを取得するのを防ぐために、このアプローチを実際に採用する必要があります。

于 2012-04-25T21:07:53.137 に答える