web-dev-qa-db-fra.com

HttpClient: la chaîne d'URI est trop longue

Compte tenu de la tentative suivante de publication de données sur un service Web générant des fichiers PDF, PDF est une fusée (ce qui est génial par ailleurs).

J'ai l'erreur URI non valide: la chaîne d'URI est trop longue
Pourquoi quelqu'un imposerait-il une limite arbitraire aux données 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;
}

Je reçois cette erreur ridicule.

 {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

Cela me rappelle que 640k devrait suffire ... Je veux dire vraiment?

13
Jim

Avec un post peut inclure le contenu dans le message http au lieu de l'URI. Un uri a une longueur maximale de 2083 caractères. Vous pouvez l'envoyer sous forme de code JSON dans le message http au lieu de l'URI, qui est le moyen recommandé pour envoyer de gros morceaux de données dans un HttpPost/HttpPut. J'ai modifié votre code pour l'utiliser. Cela suppose que votre service que vous contactez peut fonctionner avec JSON (.net Web Api prêt à l'emploi ne devrait pas poser de problème).

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;
}

Assurez-vous d’installer newtonsoft json .

11
Igor

Je viens de résoudre un problème similaire. Pour moi, j’intégrais avec un backend que je ne contrôlais pas et que je devais POST] avec des données de formulaire (par exemple, customerID) sous forme de variables de formulaire. Donc, passer à JSON ou Multipart romprait le backend que je ne contrôlais pas. Le problème était que des fichiers volumineux provoqueraient une erreur dans le FormUrlEncodedContent en indiquant "La chaîne uri est trop longue".

C'est le code qui l'a résolu après deux jours d'effort (la note doit encore être modifiée pour être 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();
            }



        }

    }
7
Brian

@Mick Byrne: Merci. Votre solution a fonctionné à merveille!

Voici mon code complet:

      public async Task DateienSendenAsync (string PfadUndDatei, string Dateiname, String VRPinGUID, String ProjektGUID, String VRPinX, String VRPinY, String VRPinZ)
    {
        var client = new HttpClient();
        // Create the HttpContent for the form to be posted.
        var requestContent = new[] {
                            new KeyValuePair<string, string>("dateiname", Dateiname),

                            new KeyValuePair<string, string>("bild", Convert.ToBase64String(File.ReadAllBytes(PfadUndDatei))),
                            new KeyValuePair<string, string>("VRPinGUID", VRPinGUID),
                            new KeyValuePair<string, string>("ProjektGUID", ProjektGUID),
                            new KeyValuePair<string, string>("ebene", "ebene"),
                            new KeyValuePair<string, string>("raumnummer", "raumnummer"),
                            new KeyValuePair<string, string>("ansichtsname", "ansichtsname"),
                            new KeyValuePair<string, string>("VRPinX", VRPinX),
                            new KeyValuePair<string, string>("VRPinY", VRPinY),
                            new KeyValuePair<string, string>("VRPinZ", VRPinZ),

                            };

        String url = "http://yourhomepage/path/upload.php";

        var encodedItems = requestContent.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);



    }
2
Robert Stefanowicz

Si, comme moi, vous êtes confronté à un service Web tierce qui n'acceptera que le contenu d'un formulaire, vous pouvez contourner le problème de la manière suivante:

// 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);
1
Mick Byrne