ASP.NET WebMethod如何将byte[]转换为Base64字符串返回?
如何将WebMethod返回的byte[]属性序列化为Base64字符串
我有一个返回包含byte[]属性的Object类型的WebMethod,通过Ajax调用返回至浏览器时,JSON响应中的byte[]会以字节数组形式显示(如"image":[255,216,255,224,0,16,74,70,73,...]),想知道怎么把它转换成Base64字符串。
相关代码
WebMethod代码
[WebMethod] public static Object GetDataEndpoint() { List<Prestation> data = GetPrestations(); return data; }
返回对象(来自外部库)
[System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] [System.Runtime.Serialization.DataContractAttribute(Name="Prestation", Namespace="http://schemas.datacontract.org/2004/07/yyy")] [System.SerializableAttribute()] public partial class Prestation : XXX.BusinessEntityBase { // ... 其他属性 ..... [System.Runtime.Serialization.OptionalFieldAttribute()] private byte[] imageField; [System.Runtime.Serialization.DataMemberAttribute()] public byte[] image { get { return this.imageField; } set { if ((object.ReferenceEquals(this.imageField, value) != true)) { this.imageField = value; this.RaisePropertyChanged("image"); } } } }
Web.config配置片段
<system.web.extensions> <scripting> <webServices> <jsonSerialization maxJsonLength="50000000" /> </webServices> </scripting> </system.web.extensions>
解决方案
因为Prestation类来自外部库无法直接修改,推荐以下几种可行的处理方式:
方法一:创建DTO映射转换
新建一个数据传输对象(DTO),将原对象的byte[]属性转换为Base64字符串后返回,完全控制序列化结果。
// 定义DTO类,复制需要的属性 public class PrestationDto { // 原类的其他属性,按需添加 // public int Id { get; set; } // public string Name { get; set; } public string image { get; set; } } // 修改WebMethod返回DTO列表 [WebMethod] public static List<PrestationDto> GetDataEndpoint() { List<Prestation> data = GetPrestations(); return data.Select(p => new PrestationDto { // 映射其他属性 // Id = p.Id, // Name = p.Name, image = p.image != null ? Convert.ToBase64String(p.image) : null }).ToList(); }
方法二:自定义JSON序列化转换器
通过实现JavaScriptConverter,全局配置将所有byte[]序列化为Base64字符串。
- 实现转换器类:
public class ByteArrayConverter : JavaScriptConverter { public override IEnumerable<Type> SupportedTypes { get { return new List<Type> { typeof(byte[]) }; } } public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { byte[] bytes = (byte[])obj; return new Dictionary<string, object> { { "image", bytes != null ? Convert.ToBase64String(bytes) : null } }; } public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { // 如需反序列化,可将Base64转回byte[] if (dictionary.ContainsKey("image") && dictionary["image"] is string base64) { return Convert.FromBase64String(base64); } return null; } }
- 在Web.config中注册转换器:
<system.web.extensions> <scripting> <webServices> <jsonSerialization maxJsonLength="50000000"> <converters> <add name="ByteArrayConverter" type="你的命名空间.ByteArrayConverter, 你的程序集名称"/> </converters> </jsonSerialization> </webServices> </scripting> </system.web.extensions>
方法三:手动使用DataContractJsonSerializer序列化
直接在WebMethod中使用DataContractJsonSerializer,通过代理类将byte[]转为Base64。
[WebMethod] public static void GetDataEndpoint() { List<Prestation> data = GetPrestations(); HttpContext.Current.Response.ContentType = "application/json"; var settings = new DataContractJsonSerializerSettings { DataContractSurrogate = new ByteArraySurrogate() }; var serializer = new DataContractJsonSerializer(typeof(List<Prestation>), settings); serializer.WriteObject(HttpContext.Current.Response.OutputStream, data); } // 实现数据契约代理处理byte[] public class ByteArraySurrogate : IDataContractSurrogate { public Type GetDataContractType(Type type) { // 将byte[]类型替换为string类型序列化 return type == typeof(byte[]) ? typeof(string) : type; } public object GetObjectToSerialize(object obj, Type targetType) { if (obj is byte[] bytes) { return Convert.ToBase64String(bytes); } return obj; } // 以下为接口默认实现,按需修改 public object GetDeserializedObject(object obj, Type targetType) => obj; public object GetCustomDataToExport(Type clrType, Type dataContractType) => null; public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType) => null; public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes) { } public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) => null; public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit) => typeDeclaration; }
内容的提问来源于stack exchange,提问作者Matthieu Charbonnier
相关产品推荐
相关产品推荐

