Curl -F equivalent in C#

前端 未结 1 513
梦毁少年i
梦毁少年i 2021-01-13 02:55

I am trying to use HTTPClient object in C# to send a post request to an API. This is the CURL command:

curl -X POST https://zzz.zzz.zzz/yyy -F Key=abcd -F me         


        
1条回答
  •  -上瘾入骨i
    2021-01-13 03:19

    When sending a POST it is important that the Content-Type you send to server is indeed the one the server expects. You can easily verify what is send with the -trace option from curl:

    curl -v --trace - -X POST http://localhost -F Key=abcd -F media=@"image.txt"
    

    When you run this you'll find somewhere in first few lines this:

    00b0: 63 6f 6e 74 69 6e 75 65 0d 0a 43 6f 6e 74 65 6e continue..Conten
    00c0: 74 2d 54 79 70 65 3a 20 6d 75 6c 74 69 70 61 72 t-Type: multipar
    00d0: 74 2f 66 6f 72 6d 2d 64 61 74 61 3b 20 62 6f 75 t/form-data; bou
    00e0: 6e 64 61 72 79 3d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d ndary=----------
    00f0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d ----------------
    0100: 2d 2d 61 61 62 64 66 31 66 66 38 35 66 66 0d 0a --aabdf1ff85ff..
    0110: 0d 0a                                           ..
    

    So curl is sending an Content-Type of multipart/form-data;

    In your code you use the class FormUrlEncodedContent which states in its description:

    A container for name/value tuples encoded using application/x-www-form-urlencoded MIME type.

    So that is not the correct Conent-Type.

    A better match is the MultipartFormDataContent because it states:

    Provides a container for content encoded using multipart/form-data MIME type.

    With the correct classes found we only need to build up the container:

    var dataContent = new MultipartFormDataContent();
    var keyValue = new ByteArrayContent( Encoding.ASCII.GetBytes("abcd") );
    dataContent.Add(keyValue, "key");
    
    using (var client = new HttpClient())
    {
        // open your file
        using (var fs = File.OpenRead(@"c:\path\to\audio.acc"))
        {
            // create StreamContent from the file   
            var fileValue = new StreamContent(fs);
            // add the name and meta-data 
            dataContent.Add(fileValue, "media", "audio.acc");
    
            HttpResponseMessage response = await client.PostAsync(
                      "http://yoursite.org", 
                      dataContent);
    
            HttpContent responseContent = response.Content;
    
            using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
            {
                Console.WriteLine(await reader.ReadToEndAsync());
            }
        }
    }
    

    Running this code reveals in Fiddler:

    POST / HTTP/1.1
    Content-Type: multipart/form-data; boundary="f7335f00-bc16-4518-ae7a-149491403792"
    Host: yoursite.org
    Content-Length: 1014
    Expect: 100-continue
    Connection: Keep-Alive
    
    --f7335f00-bc16-4518-ae7a-149491403792
    Content-Disposition: form-data; name=key
    
    abcd
    --f7335f00-bc16-4518-ae7a-149491403792
    Content-Disposition: form-data; name=media; filename=audio.acc; filename*=utf-8''audio.acc
    

    which is more in line with the trace output from curl.

    0 讨论(0)
提交回复
热议问题