从HttpWebRequest读取响应时出错

时间:2012-07-25 15:22:49

标签: c# filestream httpwebresponse

我正在尝试通过网络发送1GB文本文件的内容。我修改了 suggested code 以进行基本身份验证,并保留如下:

        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();

1 个答案:

答案 0 :(得分:1)

您引用的文章说

  

如果Microsoft Internet信息服务(IIS)Web服务器配置为使用基本身份验证,并且您必须将HttpWebRequest.AllowWriteStreamBuffering属性设置为false,则必须先发送HEAD请求以在发送POST之前对连接进行预身份验证或PUT请求。

编辑 - 现在有更多的澄清!

要重述该文章,如果要将大文件发送到需要基本身份验证的目标,则需要发出两个单独的请求。这里的关键是你要设置PreAuthenticate = true。按字面意思阅读语句 - 通过将属性设置为true,您说您将在实际尝试之前验证您所做的任何请求 框架不知道您是怎么做的想要完成此预身份验证,因此您需要通过向目标发送HEAD请求来自行执行该操作。可以将HEAD HTTP方法视为实际请求的序言 - 它描述(或请求有关特定资源的信息)。

所以这个过程是这样的:

  1. http://someurl/aresource发出包含您要使用的凭据的HEAD请求,以便将此客户端的未来请求发送到该服务器以获取列出的资源
  2. 服务器将响应(理想情况下)“OK - 您可以继续。您已通过身份验证”
  3. 服务器立即感到遗憾的是'它决定允许该操作,因为它发现自己保存了一个非常大的文件: - )
  4. 我没有看到你在你发布的代码中的任何地方发出了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.