使用 HttpClient 时如何在 HttpContent 中设置大字符串?

Posted

技术标签:

【中文标题】使用 HttpClient 时如何在 HttpContent 中设置大字符串?【英文标题】:How to set large string inside HttpContent when using HttpClient? 【发布时间】:2014-05-16 20:05:49 【问题描述】:

所以,我创建了一个HttpClient 并使用HttpClient.PostAsync() 发布数据。

我使用

设置HttpContent

HttpContent content = new FormUrlEncodedContent(post_parameters);其中post_parameters 是键值对列表List<KeyValuePair<string, string>>

问题是,当HttpContent 的值很大时(转换为base64 的图像要传输)我得到一个URL 太长的错误。这是有道理的——因为网址不能超过 32,000 个字符。但是如果不是这种方式,我该如何将数据添加到HttpContent

请帮忙。

【问题讨论】:

我很困惑...当您使用任何类型的HttpContent(包括FormUrlEncodedContent)时,数据在正文中而不是在网址中..那么您为什么会在其中看到数据网址? 当我进行以下调用时, dict.Add(new KeyValuePair("Base64FileData", image)); (其中 image 是 base 64 转换后的字符串)。抛出异常。 【参考方案1】:

我在朋友的帮助下想通了。您想要做的是避免使用 FormUrlEncodedContent(),因为它对 uri 的大小有限制。相反,您可以执行以下操作:

    var jsonString = JsonConvert.SerializeObject(post_parameters);
    var content = new StringContent(jsonString, Encoding.UTF8, "application/json");

在这里,我们不需要使用 HttpContent 来发布到服务器,StringContent 就完成了!

【讨论】:

> 在这里,我们不需要使用 HttpContent 来发布到服务器,StringContent 完成了工作! StringContent实际上是HttpContent(它源自抽象HttpContent类似于FormUrlEncodedContent 这是迄今为止最简单的方法。直到 2016 年初我在这里看到的任何其他东西都是 PITA。 为我工作,感谢您的帮助。【参考方案2】:

FormUrlEncodedContent内部使用Uri.EscapeDataString:通过反射,我可以看到这个方法有限制请求长度大小的常量。

一种可能的解决方案是通过使用System.Net.WebUtility.UrlEncode (.net 4.5) 创建FormUrlEncodedContent 的新实现来绕过此限制。

public class MyFormUrlEncodedContent : ByteArrayContent

    public MyFormUrlEncodedContent(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
        : base(MyFormUrlEncodedContent.GetContentByteArray(nameValueCollection))
    
        base.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
    
    private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
    
        if (nameValueCollection == null)
        
            throw new ArgumentNullException("nameValueCollection");
        
        StringBuilder stringBuilder = new StringBuilder();
        foreach (KeyValuePair<string, string> current in nameValueCollection)
        
            if (stringBuilder.Length > 0)
            
                stringBuilder.Append('&');
            

            stringBuilder.Append(MyFormUrlEncodedContent.Encode(current.Key));
            stringBuilder.Append('=');
            stringBuilder.Append(MyFormUrlEncodedContent.Encode(current.Value));
        
        return Encoding.Default.GetBytes(stringBuilder.ToString());
    
    private static string Encode(string data)
    
        if (string.IsNullOrEmpty(data))
        
            return string.Empty;
        
        return System.Net.WebUtility.UrlEncode(data).Replace("%20", "+");
    

要发送大的内容,最好使用StreamContent。

【讨论】:

我无法使用此解决方案,因为我使用的是 .Net 4.0,并且无法访问 UrlEncode() 方法。由于工作限制,我无法升级,还有其他想法吗? 通过添加System.Web依赖,可以找到类似的方法HttpUtility.UrlEncode 这个解决方案对我有用。我在使用的 api 中有一些限制,我必须使用“application/x-www-form-urlencoded”来使用它。谢谢。 只是出于兴趣,这里发生了什么? .Replace("%20", "+") 从来没有对堆栈溢出的任何人说过这个。你真是个混蛋!【参考方案3】:

这段代码对我有用,基本上你通过http客户端在字符串内容中发送帖子数据“application/x-www-form-urlencoded”,希望这可以帮助像我一样遇到同样问题的人

void sendDocument()
    
        string url = "www.mysite.com/page.php";
        StringBuilder postData = new StringBuilder();
        postData.Append(String.Format("0=1&", HttpUtility.htmlEncode("prop"), HttpUtility.HtmlEncode("value")));
        postData.Append(String.Format("0=1", HttpUtility.HtmlEncode("prop2"), HttpUtility.HtmlEncode("value2")));
        StringContent myStringContent = new StringContent(postData.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded");
        HttpClient client = new HttpClient();
        HttpResponseMessage message = client.PostAsync(url, myStringContent).GetAwaiter().GetResult();
        string responseContent = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    

【讨论】:

但是 OP 的问题是发布大量数据,您没有证明可以通过这种方式完成。但是我看到你在做什么 - 使用 application/x-www-form-urlencoded 但绕过使用似乎有内容长度限制的 class FormUrlEncodedContent 这基本上对我有用。我改变的是使用WebUtility.UrlEncode("prop2") 而不是HtmlEncode。我有一个奇怪的 API 端点,需要在表单帖子正文中使用 JSON 数组。有时这个数组可能很大,这就是为什么我需要这样的东西。好东西!

以上是关于使用 HttpClient 时如何在 HttpContent 中设置大字符串?的主要内容,如果未能解决你的问题,请参考以下文章

使用 HttpClient 类时如何对代理进行身份验证?

使用 HttpClient.GetAsync() 时如何确定 404 响应状态

使用 System.Net.HttpClient 进行上传时如何跟踪进度? [复制]

在 Java 11 及更高版本中使用 HttpClient 时如何跟踪 HTTP 303 状态代码?

流动客户端主题时如何在 C# HttpClient 中设置 OIDC/OAuth 不记名令牌

使用 HttpClient 时如何不排除 Content-Type 中的字符集?