我正在尝试通过网络发送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();
答案 0 :(得分:1)
您引用的文章说
如果Microsoft Internet信息服务(IIS)Web服务器配置为使用基本身份验证,并且您必须将HttpWebRequest.AllowWriteStreamBuffering属性设置为false,则必须先发送HEAD请求以在发送POST之前对连接进行预身份验证或PUT请求。
编辑 - 现在有更多的澄清!
要重述该文章,如果要将大文件发送到需要基本身份验证的目标,则需要发出两个单独的请求。这里的关键是你要设置PreAuthenticate = true
。按字面意思阅读语句 - 通过将属性设置为true
,您说您将在实际尝试之前验证您所做的任何请求 框架不知道您是怎么做的想要完成此预身份验证,因此您需要通过向目标发送HEAD
请求来自行执行该操作。可以将HEAD
HTTP方法视为实际请求的序言 - 它描述(或请求有关特定资源的信息)。
所以这个过程是这样的:
http://someurl/aresource
发出包含您要使用的凭据的HEAD请求,以便将此客户端的未来请求发送到该服务器以获取列出的资源我没有看到你在你发布的代码中的任何地方发出了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.