2

このページのコメント:

http://msdn.microsoft.com/en-us/library/12s31dhy%28v=VS.90%29.aspx

..TransmitFile()はUNC共有では使用できないことを示しています。私の知る限り、これは事実です。試行すると、イベントログに次のエラーが表示されます。

TransmitFile failed. File Name: \\myshare1\e$\file.zip, Impersonation Enabled: 0, Token Valid: 1, HRESULT: 0x8007052e

推奨される代替方法はWriteFile()を使用することですが、ファイルをメモリにロードするため、これには問題があります。私のアプリケーションでは、ファイルは> 200MBであるため、これはスケーリングされません。

ASP.NETに、ユーザーにファイルをストリーミングするための方法はありますか?

  • スケーラブル(ファイル全体をRAMに読み込んだり、ASP.NETスレッドを占有したりしません)
  • UNC共有で動作します

ネットワークドライブを仮想ディレクトリとしてマッピングすることは、私たちの選択肢ではありません。ファイルをローカルWebサーバーにもコピーしないようにします。

ありがとう

4

7 に答える 7

1

リモート UNC パスをホーム ディレクトリとして使用して IIS vroot を設定しようとしましたか? うまくいけば、これが最も簡単な解決策かもしれません。ファイルに認証バリアを適用することはできますが (たとえば、HttpModule を介して、またはおそらくすぐに使用できるフォーム認証モジュールを介して)、認証フィルターが許可されたら、IIS を使用してコンテンツを効率的にストリーミングすることができます。

注意: UNC シナリオで IIS を最後に構成したのはずっと前 (1998 年!!!) で、リモート マシンでファイルがロックされるという断続的な問題に遭遇し、ファイルの更新が時々問題になりました。UNC サーバーの再起動後の復旧処理も興味深いものでした。それから 11 年が経ち、これらの問題は解消されたと思いますが、確実なことはありません。

もう 1 つの方法は、UNC マシンに Web サーバーをインストールしてから、新しいIIS7 アプリケーション リクエスト ルーティングモジュールのようなリバース プロキシ サーバーを Web サーバーにインストールすることです。

サーバー スレッドを結び付けたい場合は、KB812406で推奨されている、RAM の消費、タイムアウト、クライアントの切断などの問題に対処する方法を使用できます。必ず応答バッファリングをオフにしてください。

理想的な最大制御ソリューションは、出力を一度に送信する代わりに、ASP.NET にストリームを返し、クライアントへの結果のチャンクに関する詳細を ASP.NET に処理させることができる「ストリーミング HttpHandler」です。 、切断の処理など。しかし、これを行う良い方法を見つけることができませんでした。:-(

于 2009-11-17T20:04:38.407 に答える
0

UNCを指す別のIISWebサイトをセットアップして、それらを他のWebサイトのファイルにリダイレクトできますか?

Response.Redirect( " http://files.somewhere.com/some/file.blah ");

そうすれば、別のワーカープロセスで実行され、現在のサイトに影響を与えることはなく、ファイルはIISによって直接提供されます。これは明らかに最適です。

于 2009-11-17T17:33:36.213 に答える
0

実際に返されたエラーは、ファイル共有へのログオンの失敗でした (これは、IIS を実行している可能性が高いユーザーと、管理共有にアクセスしようとしていることを考えると、それほど驚くべきことではありません)。TransmitFile の特定の制限ではなく、それが問題であるかどうかを確認するためだけに、アクセス制限のない共有を設定しようとしましたか。

これで問題が解決した場合は、現在のユーザーとして何らかの方法でその共有にログインするか、権限を持つユーザーになりすます必要があります。

また、リフレクター TransmitFile を少し調べた後、ファイルをメモリに読み込む可能性があること、および WriteFile には、ファイルをメモリに読み込むかどうかを決定するブール値を取る別のバージョンがあることも指摘する価値があります (実際、デフォルトの WriteFile はこのパラメーターに対して false を渡します)。コードをいじる価値があるかもしれません。

于 2009-11-21T09:03:07.420 に答える
0

を使用してネットワーク ファイルを開き、FileStreamループを使用してファイルのチャンクを読み取り、チャンクを送信し ( を使用Response.Write(Char[], Int32, Int32))、チャンクを破棄し、ファイルが完全に読み取られるまで繰り返します。

于 2009-10-30T23:42:38.927 に答える
0

2 番目のサイト アプローチをお勧めし、トークン ベースの認証メカニズムを実装します。Redirect 経由でクライアントに渡される URL に認証 Cookie をエンコードします。これは、舞台裏で共有される不透明な値である場合もあれば、秘密のパスワードと現在の日付のハッシュのような単純なものである場合もあります。

私が行ったあるプロジェクトでは、ハッシュを使用しました。1 つのサーバーが、共有秘密パスワードと内線番号のハッシュを生成しました。2 番目のサーバー (別のネットワーク上にあった) は、同じパスワードと内線番号を取得し、それらをハッシュして、ユーザーがその内線番号から目的の電話番号に電話をかけることが許可されていることを確認しました。

于 2009-11-24T01:25:07.270 に答える
0

ファイルをローカル ディレクトリに書き込み、robocopy ジョブでディレクトリを監視してコピーを実行できます。

ただし、ローカル サーバーへの書き込みは避けたいので、ターゲット サーバーにサーバー (HTTP や FTP など) を配置し、そのサービスにファイルを書き込むことを検討することをお勧めします。

于 2009-11-17T17:20:34.227 に答える
-1

TransmitFile のコードは非常に単純です。必要に応じて変更してみませんか?

public void TransmitFile(string filename, long offset, long length)
{
    if (filename == null)
    {
        throw new ArgumentNullException("filename");
    }
    if (offset < 0L)
    {
        throw new ArgumentException(SR.GetString("Invalid_range"), "offset");
    }
    if (length < -1L)
    {
        throw new ArgumentException(SR.GetString("Invalid_range"), "length");
    }
    filename = this.GetNormalizedFilename(filename);
    using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        long num = stream.Length;
        if (length == -1L)
        {
            length = num - offset;
        }
        if (num < offset)
        {
            throw new ArgumentException(SR.GetString("Invalid_range"), "offset");
        }
        if ((num - offset) < length)
        {
            throw new ArgumentException(SR.GetString("Invalid_range"), "length");
        }
        if (!this.UsingHttpWriter)
        {
            this.WriteStreamAsText(stream, offset, length);
            return;
        }
    }
    if (length > 0L)
    {
        bool supportsLongTransmitFile = (this._wr != null) && this._wr.SupportsLongTransmitFile;
        this._httpWriter.TransmitFile(filename, offset, length, this._context.IsClientImpersonationConfigured || HttpRuntime.IsOnUNCShareInternal, supportsLongTransmitFile);
    }
}



private void WriteStreamAsText(Stream f, long offset, long size)
{
    if (size < 0L)
    {
        size = f.Length - offset;
    }
    if (size > 0L)
    {
        if (offset > 0L)
        {
            f.Seek(offset, SeekOrigin.Begin);
        }
        byte[] buffer = new byte[(int) size];
        int count = f.Read(buffer, 0, (int) size);
        this._writer.Write(Encoding.Default.GetChars(buffer, 0, count));
    }
}


internal void TransmitFile(string filename, long offset, long size, bool isImpersonating, bool supportsLongTransmitFile)
{
    if (this._charBufferLength != this._charBufferFree)
    {
        this.FlushCharBuffer(true);
    }
    this._lastBuffer = null;
    this._buffers.Add(new HttpFileResponseElement(filename, offset, size, isImpersonating, supportsLongTransmitFile));
    if (!this._responseBufferingOn)
    {
        this._response.Flush();
    }
}

ありがとう、

フィル。

于 2009-11-24T16:14:59.023 に答える