0

1GBのテキストファイルの内容をネットワーク経由で送信しようとしています。基本認証用に提案されたコードを変更し、次のように保持しました。

        WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);

        WRequest.Credentials = Credentials;
        WRequest.PreAuthenticate = true;

        WRequest.ContentType = "text/plain"; 
        WRequest.Method = "POST";
        WRequest.AllowWriteStreamBuffering = false;
        WRequest.Timeout = 10000;

        FileStream ReadIn = new FileStream(filename, FileMode.Open, FileAccess.Read);
        ReadIn.Seek(0, SeekOrigin.Begin); 
        WRequest.ContentLength = ReadIn.Length; 
        Byte[] FileData = new Byte[ReadIn.Length]; 
        int DataRead = 0;
        Stream tempStream = WRequest.GetRequestStream();
        do
        {
            DataRead = ReadIn.Read(FileData, 0, 2048);
            if (DataRead > 0) 
            {
                tempStream.Write(FileData, 0, DataRead);
                Array.Clear(FileData, 0, 2048); 
            }
        } while (DataRead > 0);


        // The response
        WResponse = (HttpWebResponse)WRequest.GetResponse();

ただし、System.Net.ProtocolViolationExceptionエラーが発生します:「[Begin] GetResponseを呼び出す前に、ContentLengthバイトをリクエストストリームに書き込む必要があります」。HttpWebRequest.BeginGetRequestResponse ...を確認しましたが、デバッグの結果、WRequestのcontentlengthが-1ではないことがわかりました。他に何がうまくいかない可能性がありますか?どのように応答を取得する必要がありますか?

更新:小さなファイルで機能したコードは次のとおりです:

        WebRequest request = WebRequest.Create(url);
        request.Method = "POST";
        request.Credentials = Credentials;


        using (StreamReader reader = new StreamReader(filename))
        {
                postData = reader.ReadToEnd();
        }

        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentType = "text/plain";
        request.ContentLength = byteArray.Length;

        Stream dataStream = request.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();

        // The response
        WebResponse response = request.GetResponse();
        Console.WriteLine(((HttpWebResponse)response).StatusDescription);

        dataStream = response.GetResponseStream();

        using (StreamReader reader = new StreamReader(dataStream))
        {
             responseFromServer = reader.ReadToEnd();
        }

        dataStream.Close();
        response.Close();
4

1 に答える 1

1

あなたが参照した記事は言う

Microsoftインターネットインフォメーションサービス(IIS)Webサーバーが基本認証を使用するように構成されており、HttpWebRequest.AllowWriteStreamBufferingプロパティをfalseに設定する必要がある場合は、POSTまたはPUT要求を送信する前に、接続を事前認証するためにHEAD要求を送信する必要があります。 。

編集-より明確になりました!

記事を言い換えると、基本認証を必要とする宛先に大きなファイルを送信する場合は、2つの別々の要求を発行する必要があります。ここで重要なのは、設定していることですPreAuthenticate = true。ステートメントを文字通り読んでください-プロパティをに設定することで、実際にリクエストを試みる前にtrue、行ったリクエストを認証すると言っています!フレームワークは、この事前認証をどのように実行するかを認識していないため、宛先に要求を送信して、自分でそのアクションを実行する必要があります。HTTPメソッドは、実際のリクエストのプロローグであると考えてください。特定のリソースを記述(またはリクエスト)します。HEADHEAD

したがって、プロセスは次のようになります。

  1. http://someurl/aresourceリストされたリソースに対してこのクライアントからそのサーバーに将来の要求を行うときに使用する資格情報を含むHEAD要求を行います
  2. サーバーは(理想的には)「OK-続行できます。認証されました」と応答します。
  3. サーバーは、非常に大きなファイルを保存していることに気付いたため、操作を許可するという決定をすぐに後悔しています:-)

投稿したコードのどこにもHEADリクエストを行っていないようです。まだない場合は、コードの先頭に追加してください(OPのサンプル記事refから抜粋)。

//preAuth the request
// You can add logic so that you only pre-authenticate the very first request.
// You should not have to pre-authenticate each request.
WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
// Set the username and the password.
WRequest.Credentials = new NetworkCredential(user, password);
WRequest.PreAuthenticate = true;
WRequest.UserAgent = "Upload Test";
WRequest.Method = "HEAD";
WRequest.Timeout = 10000;
WResponse = (HttpWebResponse)WRequest.GetResponse(); 
WResponse.Close();
// Make the real request.
于 2012-07-25T17:33:13.957 に答える