问题 HttpClient:uri字符串太长


鉴于以下尝试将数据发布到生成PDF文件的Web服务, PDF火箭 (顺便说一下这真棒)。

我收到了错误 无效的URI:uri字符串太长
为什么有人会施加任意限制 POSTed数据?

using (var client = new HttpClient())
{
    // Build the conversion options
    var options = new Dictionary<string, string>
    {
        { "value", html },
        { "apikey", ConfigurationManager.AppSettings["pdf:key"] },
        { "MarginLeft", "10" },
        { "MarginRight", "10" }
    };

    // THIS LINE RAISES THE EXCEPTION
    var content = new FormUrlEncodedContent(options);

    var response = await client.PostAsync("https://api.html2pdfrocket.com/pdf", content);
    var result = await response.Content.ReadAsByteArrayAsync();
    return result;
}

我收到这个荒谬的错误。

 {System.UriFormatException: Invalid URI: The Uri string is too long.
   at System.UriHelper.EscapeString
   at System.Uri.EscapeDataString
   at System.Net.Http.FormUrlEncodedContent.Encode
   at System.Net.Http.FormUrlEncodedContent.GetContentByteArray

这让我想起了 640k 应该够了......我的意思是 真?


5657
2017-07-18 15:29


起源

使用帖子可以包含h​​ttp消息中的内容而不是URI。 uri的最大长度为2083个字符。 - Igor
啊,这有道理,怎么样? - Jim
另外,为什么使用Web服务从HTML创建PDF,当您可以使用免费库自己创建PDF? - DavidG
看到 这个问题,在这种情况下,他们在http消息中将其作为json发送。以这种方式完成时,对数据长度没有限制。使用创建一个json字符串 JsonConvert.SerializeObject 然后使用发送为字符串内容 StringContent 并发送。 - Igor
因此,我说的是没有内置的等价物 HttpClient 对于 UploadValues("https://api.html2pdfrocket.com/pdf", options) 在里面 WebClient 类? - Jim


答案:


使用帖子可以包含h​​ttp消息中的内容而不是URI。 uri的最大长度为2083个字符。您可以在http消息中将其作为JSON发送而不是URI,这是在HttpPost / HttpPut中发送更大块数据的推荐方法。我改变了你的代码来使用它。这假设您正在联系的服务可以使用JSON(.net Web Api开箱即用应该没有问题)。

using (var client = new HttpClient())
{
    // Build the conversion options
    var options = new 
    {
        value = html,
        apikey = ConfigurationManager.AppSettings["pdf:key"],
        MarginLeft = "10",
        MarginRight = "10"
    };

    // Serialize our concrete class into a JSON String
    var stringPayload = JsonConvert.SerializeObject(options);
    var content = new StringContent(stringPayload, Encoding.UTF8, "application/json");

    var response = await client.PostAsync("https://api.html2pdfrocket.com/pdf", content);
    var result = await response.Content.ReadAsByteArrayAsync();
    return result;
}

一定要安装 newtonsoft json


9
2017-07-18 15:39



谢谢,我没有仔细阅读课程的名称,我认为这已经是一个常规的帖子。谢谢。 - Jim
很高兴知道是否有一个相当于的内置 WebClient, UploadValues 方法,它不使用json,仍然设法发布所有内容。 - Jim
@Jim - 这个答案 可能是你正在寻找的方法。 - Igor
谢谢,这个例子发布了一个值,但原则适用 - 疯狂它不是内置的 - 谢谢你的帮助。 - Jim
作为一个有趣的问题,我发布的数据实际上是 不 在网址中,它的发布完全像 StringContent。错误不是使用不正确的方法,错误是在任意限制 EscapeDataString那 FormUrlEncodedContent 碰巧使用。 - Jim


我刚刚解决了类似的问题。对我来说,我正在与我无法控制的后端集成,并且必须将POST文件与表单数据(例如customerID)一起作为表单变量。因此切换到JSON或Multipart会破坏我无法控制的后端。问题是大文件会导致FormUrlEncodedContent抛出错误,说“uri字符串太长”。

这是经过两天努力后为我解决的代码(注意仍然需要调整为ASYNC)。

private string UploadFile(string filename, int CustomerID, byte[] ImageData) {

        string Base64String = "data:image/jpeg;base64," + Convert.ToBase64String(ImageData, 0, ImageData.Length);

        var baseAddress = new Uri("[PUT URL HERE]");
        var cookieContainer = new CookieContainer();
        using (var handler = new HttpClientHandler() { AllowAutoRedirect = true, UseCookies = true, CookieContainer = cookieContainer })
        using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
        {

            try {

                //ENCODE THE FORM VARIABLES DIRECTLY INTO A STRING rather than using a FormUrlEncodedContent type which has a limit on its size.        
                string FormStuff = string.Format("name={0}&file={1}&id={2}", filename, HttpUtility.UrlEncode(Base64String), CustomerID.ToString());
                //THEN USE THIS STRING TO CREATE A NEW STRINGCONTENT WHICH TAKES A PARAMETER WHICH WILL FormURLEncode IT AND DOES NOT SEEM TO THROW THE SIZE ERROR
                StringContent content = new StringContent(FormStuff, Encoding.UTF8, "application/x-www-form-urlencoded");

                //UPLOAD
                string url = string.Format("/ajax/customer_image_upload.php");
                response = client.PostAsync(url, content).Result;
                return response.Content.ToString();

            }
            catch (Exception ex) {
                return ex.ToString();
            }



        }

    }

5
2018-01-23 03:52



这项工作对我而言。 - Miguel Angel Muñoz


如果像我一样,你面对的是一些只接受表单内容的第三方网络服务,你可以解决这个问题:

// Let's assume you've got your key-value pairs organised into a nice Dictionary<string, string> called formData
var encodedItems = formData.Select(i => WebUtility.UrlEncode(i.Key) + "=" + WebUtility.UrlEncode(i.Value));
var encodedContent = new StringContent(String.Join("&", encodedItems), null, "application/x-www-form-urlencoded");

// Post away!
var response = await client.PostAsync(url, encodedContent);

0
2017-08-15 07:07