首页 > 其他分享 >使用 HttpWebRequest 类发送大量数据时,POST 或 PUT 请求失败

使用 HttpWebRequest 类发送大量数据时,POST 或 PUT 请求失败

时间:2024-04-23 17:33:40浏览次数:22  
标签:WResponse 身份验证 ReadIn HttpWebRequest PUT Close POST WRequest

本文可帮助你解决在使用 HttpWebRequest 类在运行 Microsoft .NET Framework的计算机上发送大量数据时可能会引发错误的问题。

原始产品版本:.NET Framework
原始 KB 编号: 908573

症状

当你使用 HttpWebRequest 类通过 POST 或 PUT 请求发送大量数据时,请求可能会在运行 .NET Framework 的计算机上失败。 此外,还可能会收到内存不足或超时错误消息。

如果未收到内存不足或超时错误消息,你可能会注意到使用 HttpWebRequest 类的应用程序会占用大量内存。 使用 性能监视器 监视使用 HttpWebRequest 类的应用程序时,随着数据的发送,专用字节数将继续增加。 因此,由于内存和资源利用率增加,计算机和其他应用程序中的性能也可能会降低。

 备注

默认情况下,可以上传的数据量会因计算机上的内存和资源而异。

原因

出现此问题的原因是,使用 HttpWebRequest 类时,默认情况下,.NET Framework会缓冲传出数据。

解决方法

若要解决此问题,请将 HttpWebRequest.AllowWriteStreamBuffering 属性设置为 false。

解决方法导致的错误

将 属性设置为 HttpWebRequest.AllowWriteStreamBuffering false 时,可能会收到类似于以下示例的错误消息:

此请求需要缓冲数据才能成功进行身份验证重定向。

若要在属性设置为 false 时HttpWebRequest.AllowWriteStreamBuffering使用 POST 或 PUT 请求成功发送大量数据,请使用以下方法之一,具体取决于要使用的身份验证方法之一。

匿名身份验证

如果 Web 服务器配置为使用匿名身份验证,请将 HttpWebRequest.AllowWriteStreamBuffering 属性设置为 false。 无需进行其他更改。

基本身份验证

如果 Internet Information Services (IIS) Web 服务器配置为使用基本身份验证,并且你可以将 属性设置为 HttpWebRequest.AllowWriteStreamBuffering false,则必须在发送 POST 或 PUT 请求之前发送HEAD对连接进行预身份验证的请求。 还应将 HttpWebRequest.PreAuthenticate 属性设置为 true。 然后,发送 POST 或 PUT 请求,然后接收响应。 为此,请使用类似于以下代码示例的代码。

C#
public void test(Uri URL)
{
    HttpWebRequest WRequest;
    HttpWebResponse WResponse;
    //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.
    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 = "POST";
    WRequest.AllowWriteStreamBuffering = false;
    WRequest.Timeout = 10000;
    FileStream ReadIn = new FileStream("c:\\testuploadfile.txt", FileMode.Open, FileAccess.Read);
    ReadIn.Seek(0, SeekOrigin.Begin); // Move to the start of the file.
    WRequest.ContentLength = ReadIn.Length; // Set the content length header to the size of the file.
    Byte[] FileData = new Byte[ReadIn.Length]; // Read the file in 2 KB segments.
    int DataRead = 0;
    Stream tempStream = WRequest.GetRequestStream();
    do
    {
        DataRead = ReadIn.Read(FileData,0,2048);
        if (DataRead > 0) //we have data
        {
            tempStream.Write(FileData,0,DataRead);
            Array.Clear(FileData,0, 2048); // Clear the array.
        }
    } while (DataRead > 0);

    WResponse = (HttpWebResponse)WRequest.GetResponse();
    // Read your response data here.
    // Close all streams.
    ReadIn.Close();
    tempStream.Close();
    WResponse.Close();
}

 备注

根据应用程序的设计方式,可能不必通过发送 HEAD 请求来预验证每个请求。

集成 Windows 身份验证

可以使用 Negotiate 或 Windows 质询/响应 (NTLM) Windows 身份验证 来配置安装 IIS 以做出响应的计算机。 如果 IIS 配置为使用 Negotiate for Windows 身份验证,则客户端可以使用 Kerberos 或 NTLM 进行身份验证。 如果 IIS 配置为使用 NTLM 身份验证,则只能使用 NTLM 身份验证,并且不支持 Kerberos 身份验证。

如果使用与 Kerberos 身份验证协商,请使用以下解决方法。 如果使用 NTLM,解决方法将失败。

协商 Kerberos 身份验证

如果 IIS Web 服务器配置为使用协商身份验证,并且必须将 属性设置为 HttpWebRequest.AllowWriteStreamBuffering false,则必须发送HEAD请求以在发送 POST 或 PUT 请求之前对连接进行预身份验证。 还可以将 HttpWebRequest.PreAuthenticate 属性设置为 true。 此外,可能必须将 属性设置为 HttpWebRequest.UnsafeAuthenticatedConnectionSharing true。 然后,发送 POST 或 PUT 请求,然后接收响应。 为此,可以使用类似于以下代码示例的代码。

 备注

如果客户端无法将 Kerberos 与协商身份验证一起使用,则此解决方法将失败。 还必须确保 属性 HttpWebRequest.KeepAlive 设置为 true。 默认情况下,属性的设置 HttpWebRequest.KeepAlive 为 true。 Kerberos 和基本身份验证的逻辑几乎相同。

C#
public void test(Uri URL)
{
    HttpWebRequest WRequest;
    HttpWebResponse WResponse;
    CredentialCache myCredCache = new CredentialCache();
    myCredCache.Add(URL,"Negotiate",(NetworkCredential) CredentialCache.DefaultCredentials);
    // Pre-authenticate the request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // This property must be set to true for Kerberos authentication.
    WRequest.PreAuthenticate = true;
    // Keep the connection alive.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "HEAD";
    WRequest.Timeout = 10000;
    WResponse = (HttpWebResponse)WRequest.GetResponse(); 
    WResponse.Close();
    // Make the real request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // This property must be set to true for Kerberos authentication.
    WRequest.PreAuthenticate = true;
    // Keep the connection alive.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "POST";
    WRequest.AllowWriteStreamBuffering = false;
    WRequest.Timeout = 10000;
    FileStream ReadIn = new FileStream("c:\\testuploadfile.txt ", FileMode.Open, FileAccess.Read);
    ReadIn.Seek(0, SeekOrigin.Begin); // Move to the start of the file.
    WRequest.ContentLength = ReadIn.Length; // Set the content length header to the size of the file.
    Byte[] FileData = new Byte[ReadIn.Length]; // Read the file in 2 KB segments.
    int DataRead = 0;
    Stream tempStream = WRequest.GetRequestStream();
    do
    {
        DataRead = ReadIn.Read(FileData,0,2048);
        if (DataRead > 0) // We have data.
        {
            tempStream.Write(FileData,0,DataRead);
            Array.Clear(FileData,0, 2048); // Clear the array.
        }
    }while(DataRead > 0);

    WResponse = (HttpWebResponse)WRequest.GetResponse(); 
    // Read your response data here.
    // Close all streams
    ReadIn.Close();
    tempStream.Close();
    WResponse.Close();
}

 备注

根据应用程序的设计方式,可能不必通过发送HEAD请求来预验证每个请求。

NTLM 身份验证

如果 IIS Web 服务器还配置为使用 NTLM 身份验证和 Windows-Integrated 身份验证,并且必须将 属性设置为 HttpWebRequest.AllowWriteStreamBuffering false,则可以在客户端代码中将身份验证类型设置为 NTLM。 将 IIS 配置为同时使用 Negotiate 和 NTLM 身份验证并在客户端代码中将身份验证类型设置为 NTLM 后,可以通过将 IIS 元数据库中的 AuthPersistSingleRequest 属性设置为 false 来配置 IIS 处理身份验证请求的方式。

 备注

有关如何配置 IIS 以支持 Negotiate 和 NTLM 身份验证的详细信息,请参阅 参考 部分。

在发送请求并将 属性设置为 HttpWebrequest.UnsafeAuthenticatedConnectionSharing true 之前,还必须发送HEADPOST请求以对连接进行预身份验证。 然后,将 属性 HttpWebRequest.PreAuthenticate 设置为 false。 最后,发送 POST 或 PUT 请求,然后接收响应。 为此,请使用类似于以下代码示例的代码。

C#
public void test(Uri URL)
{
    HttpWebRequest WRequest;
    HttpWebResponse WResponse;
    CredentialCache myCredCache = new CredentialCache();
    myCredCache.Add(URL,"NTLM",(NetworkCredential) CredentialCache.DefaultCredentials);
    // Pre-authenticate the request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // For NTLM authentication, you must set the following property to true
    // so the connection does not close.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "HEAD";
    WRequest.Timeout = 10000;
    WResponse = (HttpWebResponse)WRequest.GetResponse(); 
    WResponse.Close();
    // Make the real request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // For NTLM authentication, you must set the following property to true
    // so the connection does not close.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "POST";
    WRequest.AllowWriteStreamBuffering = false;
    WRequest.Timeout = 10000;
    FileStream ReadIn = new FileStream("c:\\ testuploadfile.txt", FileMode.Open, FileAccess.Read);
    ReadIn.Seek(0, SeekOrigin.Begin); // Move to the start of the file.
    WRequest.ContentLength = ReadIn.Length; // Set the content length header to the size of the file.
    Byte[] FileData = new Byte[ReadIn.Length]; // Read the file in 2 KB segments.
    int DataRead = 0;
    Stream tempStream = WRequest.GetRequestStream();
    do
    {
        DataRead = ReadIn.Read(FileData,0,2048);
        if (DataRead > 0) // We have data.
        {
            tempStream.Write(FileData,0,DataRead);
            Array.Clear(FileData,0, 2048); // Clear the array.
        }
    }while(DataRead > 0);

    WResponse = (HttpWebResponse)WRequest.GetResponse();
    // Read your response data here.
    // Close all streams.
    ReadIn.Close();
    tempStream.Close();
    WResponse.Close();
}

 备注

根据应用程序的设计方式,可能不必通过发送 HEAD 请求来预验证每个请求。

References

标签:WResponse,身份验证,ReadIn,HttpWebRequest,PUT,Close,POST,WRequest
From: https://www.cnblogs.com/Alex80/p/18153370

相关文章

  • 面试官:在原生input上面使用v-model和组件上面使用有什么区别?
    前言还是上一篇面试官:来说说vue3是怎么处理内置的v-for、v-model等指令?文章的那个粉丝,面试官接着问了他另外一个v-model的问题。面试官:vue3的v-model都用过吧,来讲讲。粉丝:v-model其实就是一个语法糖,在编译时v-model会被编译成:modelValue属性和@update:modelValue事件。一......
  • 22.Postgresql的checkpoint功能
    PostgreSQL中的checkpoint是数据库管理系统(DBMS)中的一项重要机制,用于确保数据的一致性、可恢复性和性能管理。以下是关于PostgreSQLcheckpoint的详细解释:checkpoint的定义与作用定义:Checkpoint是一个在WAL(Write-AheadLog)序列中的点,此时所有数据文件已更新,反映了到该点为止......
  • postgresql重置序列和自增主键
    1.问题背景数据表中插入了几条测试数据,后又手动删除,导致后面插入数据的时候报主键冲突:ERROR:duplicatekeyvalueviolatesuniqueconstraint"tableName_pkey"DETAIL:Key(id)=(1)alreadyexists.12即使采用INSERTIGNORE的方式或者REPLACEINTO的方式还是报错,所以就想......
  • input js 只能输入数字和两位小数
    functiononlyNumber(obj){//得到第一个字符是否为负号vart=obj.value.charAt(0);//先把非数字的都替换掉,除了数字和.和-号obj.value=obj.value.replace(/[^\d\.]/g,'');//前两位不能是0加数字obj.value=obj.value.replace(/^0\d[0-9]*/g,'');......
  • ABC 287 B - Postal Card
    题目链接:由于是可以和\(T\)的多个字符串相同而仅计数一次,考虑把\(T\)中的字符串用\(\rmset\)存储已达到去重的目的。注:\(\rmset\)的\(\rmcount\)返回\(1\)表示找到了该元素,返回\(0\)则说明没找到。#include<bits/stdc++.h>usingi64=longlong;intmain......
  • Computer Basics 03 - Basic Parts of a Computer
     IntroductionThebasicpartsofadesktopcomputerarethecomputercase,monitor,keyboard,mouse,andpowercord.Eachpartplaysanimportantrolewheneveryouuseacomputer.Watchthevideobelowtolearnaboutthebasicpartsofacomputer.(Video......
  • Computer Basics 03b - Mouse tutorial
     Amouseisahandhelddevicethatletsyoupointtoobjectsonthescreen,clickthem,andmovethem.Takealookatthediagrambelowtolearnthedifferentpartsofatypicalmouse.Toscrollthroughthislesson,youcanuseyourkeyboard's down......
  • Computer Basics 04 - Buttons and Ports on a Computer
     IntroductionTakealookatthefrontandbackofyourcomputercaseandcountthenumberofbuttons,ports,andslotsyousee.Nowlookatyourmonitorandcountanyyoufindthere.Youprobablycountedatleast10,andmaybealotmore.Eachcomputer......
  • Computer Basics - Content 计算机基础 目录 Базовый каталог комп
    Introduction简介Презентация1AboutThisTutorial关于本教程ОкурсеLearnwhat'scoveredinthiscourse. 了解这个课程涵盖什么。Ознакомьтесьссодержаниемкурса2WhatisaComputer?什么是电脑?Чтота......
  • Computer Basics 01 - About this tutorial
     AboutthistutorialThistutorialwillhelpyouunderstandhowcomputersworkandhowtousethem.We'lltalkabouthowtosetupacomputer,thedifferencebetweenhardwareandsoftware,andthetypesofcomputersyoucanuse.We'llalsoexpl......