You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用BinaryFormatter反序列化Web API字节数组时遇无效二进制格式异常

问题:二进制反序列化时提示“输入流不是有效的二进制格式”

我定义了实现ISerializable接口的可序列化类Class1:

[Serializable]
public class Class1 : ISerializable
{
    public int Id { get; set; }

    public string Name { get; set; }

    public Class1() { }

    Class1(SerializationInfo info, StreamingContext context)
    {
        Id = (int)info.GetValue(nameof(Id), typeof(int));
        Name = (string)info.GetValue(nameof(Name), typeof(string));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(Id), Id);
        info.AddValue(nameof(Name), Name);
    }

    public override string ToString()
    {
        return $"{Id}; {Name}";
    }
}

我的Web API将该类序列化后以字节数组形式返回:

public class DataController : ApiController
{
    public byte[] Get()
    {
        Class1 class1 = new Class1()
        {
            Id = 100,
            Name = "Name"
        };
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        using (MemoryStream memoryStream = new MemoryStream())
        {
            binaryFormatter.Serialize(memoryStream, class1);
            return memoryStream.ToArray();
        }
    }
}

在WinForms应用中,我尝试获取该序列化后的类并还原:

private async void Button1_Click(object sender, EventArgs e)
{
    HttpClient httpClient = new HttpClient();

    Uri uri = new Uri(textBox1.Text);

    var bytes = await httpClient.GetByteArrayAsync(uri);

    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream(bytes))
    {
        var class1 = binaryFormatter.Deserialize(memoryStream) as Class1;
        richTextBox1.Text = class1.ToString();
    }
}

但调用Deserialize方法时抛出异常,提示"The input stream is not a valid binary format.",请问哪里操作有误?


原因及解决办法

核心原因

Web API默认会将byte[]类型的返回值自动做Base64编码,以文本形式返回给客户端。你WinForms端用GetByteArrayAsync拿到的其实是这个Base64字符串的UTF-8字节数组,而非序列化后的原始二进制数据,所以直接反序列化会失败。

解决方法

方法1:修改Web API,返回原始二进制流

让API直接返回二进制内容,避免自动Base64编码:

public HttpResponseMessage Get()
{
    Class1 class1 = new Class1()
    {
        Id = 100,
        Name = "Name"
    };
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream())
    {
        binaryFormatter.Serialize(memoryStream, class1);
        memoryStream.Position = 0;
        
        var response = new HttpResponseMessage(HttpStatusCode.OK);
        response.Content = new StreamContent(memoryStream);
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        return response;
    }
}

方法2:修改WinForms端,解码Base64字符串

如果不想改动API,客户端需要先将拿到的字节数组还原为Base64字符串,再解码成原始二进制数据:

private async void Button1_Click(object sender, EventArgs e)
{
    HttpClient httpClient = new HttpClient();
    Uri uri = new Uri(textBox1.Text);

    // 获取Base64格式的字符串
    string base64Content = await httpClient.GetStringAsync(uri);
    // 解码为原始二进制数据
    var rawBytes = Convert.FromBase64String(base64Content);

    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (MemoryStream memoryStream = new MemoryStream(rawBytes))
    {
        var class1 = binaryFormatter.Deserialize(memoryStream) as Class1;
        richTextBox1.Text = class1.ToString();
    }
}

额外注意事项

  • BinaryFormatter已被官方标记为过时,存在严重的安全漏洞(反序列化不可信数据可能导致代码执行),建议替换为System.Text.Json、Newtonsoft.Json或Protocol Buffers等更安全的序列化方案。
  • 确保WinForms项目中的Class1类与Web API端的定义完全一致(包括命名空间、类名、属性、序列化构造函数和GetObjectData方法),否则即使二进制正确,也会反序列化失败。

内容的提问来源于stack exchange,提问作者DotNet Developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:55:16