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 的内容长度不是-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 Internet 信息服务 (IIS) Web 服务器配置为使用基本身份验证,并且您必须将 HttpWebRequest.AllowWriteStreamBuffering 属性设置为 false,则必须在发送 POST 或 PUT 请求之前发送 HEAD 请求以对连接进行预身份验证.

编辑 - 现在有更多说明!

重述本文,如果您想将大文件发送到需要基本身份验证的目的地,您需要发出两个单独的请求。这里的关键是您正在设置PreAuthenticate = true. 从字面上阅读该语句——通过将属性设置为true,您是说您将在实际尝试之前验证您提出的任何请求!该框架不知道您希望如何完成此预身份验证,因此您需要自己执行该操作,方法是向HEAD目标发送请求。将HEADHTTP 方法视为实际请求的序幕——它描述(或请求有关)特定资源的信息。

所以过程是这样的:

  1. 发出 HEAD 请求以http://someurl/aresource包含您在将来从此客户端向该服务器发出针对所列资源的请求时要使用的凭据
  2. 服务器将响应(理想情况下)“好的 - 你可以继续。你已通过身份验证”
  3. 服务器立即后悔决定允许该操作,因为它发现自己保存了一个非常大的文件:-)

我没有看到您在您发布的代码中的任何地方发出该 HEAD 请求 - 如果它不存在,请在代码的开头添加它(摘自 OP 中的示例文章参考):

//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 回答