使用HttpClient将字节数组发布到Web API服务器

时间:2015-08-24 14:06:29

标签: c# asp.net-web-api asp.net-web-api2 dotnet-httpclient

我想将此数据发布到Web API服务器:

public sealed class SomePostRequest
{
    public int Id { get; set; }
    public byte[] Content { get; set; }
}

将此代码用于服务器:

[Route("Incoming")]
[ValidateModel]
public async Task<IHttpActionResult> PostIncomingData(SomePostRequest requestData)
{
    // POST logic here
}

和此 - 对于客户:

var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:25001/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json"));

var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
    { "id", "1" },
    { "content", "123" }
});

var result = await client.PostAsync("api/SomeData/Incoming", content);
result.EnsureSuccessStatusCode();

一切正常(至少,调试器在PostIncomingData中的断点处停止)。

由于存在byte数组,我不想将其序列化为JSON,并希望将其作为二进制数据发布以减少网络流量(类似application/octet-stream)。< / p>

如何实现这一目标?

我尝试使用MultipartFormDataContent,但看起来我无法理解,MultipartFormDataContent将如何匹配控制器方法的签名。

例如,将内容替换为:

var content = new MultipartFormDataContent();
content.Add(new FormUrlEncodedContent(new Dictionary<string, string> { { "id", "1" } }));

var binaryContent = new ByteArrayContent(new byte[] { 1, 2, 3 });
binaryContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(binaryContent, "content");

var result = await client.PostAsync("api/SomeData/Incoming", content);
result.EnsureSuccessStatusCode();

导致错误415(&#34;不支持的媒体类型&#34;)。

3 个答案:

答案 0 :(得分:4)

我已经创建了这个通用的跨平台方法来使用Json.NET库来支持BSON格式,以便我们以后可以更轻松地重用它。它在Xamarin平台上也能正常工作。

public static async HttpResponseMessage PostBsonAsync<T>(string url, T data)
{
    using (var client = new HttpClient())
    {
        //Specifiy 'Accept' header As BSON: to ask server to return data as BSON format
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/bson"));

        //Specify 'Content-Type' header: to tell server which format of the data will be posted
        //Post data will be as Bson format                
        var bSonData = HttpExtensions.SerializeBson<T>(data);
        var byteArrayContent = new ByteArrayContent(bSonData);
        byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/bson");

        var response = await client.PostAsync(url, byteArrayContent);

        response.EnsureSuccessStatusCode();

        return response;
    }
}

帮助将数据序列化为BSON格式的方法:

public static byte[] SerializeBson<T>(T obj)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (BsonWriter writer = new BsonWriter(ms))
        {
            JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(writer, obj);
        }

        return ms.ToArray();
    }
}

然后您可以像这样使用Post方法:

var response = await PostBsonAsync<SamplePostRequest>("api/SomeData/Incoming", requestData);

答案 1 :(得分:1)

Fyi,用于protobuf序列化以请求正文帖子

        LoginRequest loginRequest = new LoginRequest()
        {
            Code = "UserId",
            Password = "myPass",
            CMToken = "eIFt4lYTKGU:APA91bFZPe3XCDL2r1JUJuEQLlN3FoeFw9ULpw8ljEavNdo9Lc_-Qua4w9pTqdOFLTb92Kf03vyWBqkcvbBfYEno4NQIvp21kN9sldDt40eUOdy0NgMRXf2Asjp6FhOD1Kmubx1Hq7pc",
        };
        byte[] rawBytes = ProtoBufSerializer.ProtoSerialize<LoginRequest>(loginRequest);

        var client = new HttpClient();
        client.BaseAddress = new Uri("http://localhost:9000/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/x-protobuf"));

        //var bSonData = HttpExtensions.SerializeBson<T>(data);
        var byteArrayContent = new ByteArrayContent(rawBytes);
        byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-protobuf");

        var result = client.PostAsync("Api/Login", byteArrayContent).Result;

        Console.WriteLine(result.IsSuccessStatusCode);

答案 2 :(得分:1)

我将Byte Array转换为Base64 String进行发布:

await client.PostAsJsonAsync( apiUrl,  
    new  {
        message = "",
        content = Convert.ToBase64String(yourByteArray),
    }
);

接收者可以通过以下方式将byte array转换回Base64 string

string base64Str = (string)postBody.data;
byte[] fileBytes = Convert.FromBase64String(base64Str);