压缩ViewState后,在Convert.FromBase64String时偶尔会发生FormatException,请教是什么原因?以下是BasePage中的相关代码
- C# code
private bool viewStateCompress = false; protected bool ViewStateCompress { set { viewStateCompress = value; } get { return viewStateCompress;} } protected override void SavePageStateToPersistenceMedium(object state) { if (!viewStateCompress) { base.SavePageStateToPersistenceMedium(state); } else { Pair pair; byte[] data; byte[] compressedData; string compressedStr; object viewState = null, controlState = null; LosFormatter formatter = new LosFormatter(); commonUtil.CompressHelper CH = commonUtil.CompressHelper.getInstance(); PageStatePersister persister = this.PageStatePersister; if (state is Pair) { pair = (Pair)state; viewState = pair.First; controlState = pair.Second; } else { base.SavePageStateToPersistenceMedium(state); return; } StringWriter wViewState = new StringWriter(); StringWriter wControlState = new StringWriter(); formatter.Serialize(wViewState, viewState); string viewStateStr = wViewState.ToString(); data = Convert.FromBase64String(viewStateStr); compressedData = CH.Compress(data); compressedStr = Convert.ToBase64String(compressedData); persister.ViewState = compressedStr; formatter.Serialize(wControlState, controlState); string controlStateStr = wControlState.ToString(); data = Convert.FromBase64String(controlStateStr); compressedData = CH.Compress(data); compressedStr = Convert.ToBase64String(compressedData); persister.ControlState = compressedStr; persister.Save(); } } protected override object LoadPageStateFromPersistenceMedium() { if (!viewStateCompress) { return base.LoadPageStateFromPersistenceMedium(); } else { byte[] data; byte[] uncompressedData; string decompressedStr; object viewState, controlState; LosFormatter formatter = new LosFormatter(); commonUtil.CompressHelper CH = commonUtil.CompressHelper.getInstance(); PageStatePersister persister = this.PageStatePersister; persister.Load(); string viewStateStr = persister.ViewState.ToString(); string controlStateStr = persister.ControlState.ToString(); try { data = Convert.FromBase64String(viewStateStr); uncompressedData = CH.Decompress(data); decompressedStr = Convert.ToBase64String(uncompressedData); viewState = formatter.Deserialize(decompressedStr); data = Convert.FromBase64String(controlStateStr); uncompressedData = CH.Decompress(data); decompressedStr = Convert.ToBase64String(uncompressedData); controlState = formatter.Deserialize(decompressedStr); } catch(Exception exp) { viewState = null; controlState = null; } return new Pair(viewState, controlState); } }
------解决方案--------------------------------------------------------
笑嘻嘻学习
------解决方案--------------------------------------------------------
学习
------解决方案--------------------------------------------------------
处理过程中没有必要设计base64编码。不论你写出什么二进制值,之后会被重新编码。而读入之前也会自动解码。因此你如果进行bas64编码,应该是额外多做了一道。
另外,压缩之前也没有必要base64编码。
------解决方案--------------------------------------------------------
学习
------解决方案--------------------------------------------------------
我只知道viewstate默认是Base64形式的数据
------解决方案--------------------------------------------------------
当Convert.FromBase64String方法的参数s的长度小于 4 或不是 4 的偶数倍时,将会抛出FormatException。
参考
http://www.cnblogs.com/heliguan/articles/1060481
------解决方案--------------------------------------------------------
不知道你的 commonUtil.CompressHelper 是什么,所以没法测试。我其实怀疑这样能够压缩多少。执行压缩,并且仍然是通过internet上无数的网卡、网线、路由器来回传递,这还是比较复杂的过程。我写了一个简单的过程,不压缩,用磁盘来代替网络,可以参考一下。这里也是输出字符串,但是并不做base64编码解码。
- C# code
public class XVPage : Page{ static private DirectoryInfo _Dir; private DirectoryInfo Dir { get { if (_Dir == null) { _Dir = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data")); if (!_Dir.Exists) _Dir.Create(); _Dir = new DirectoryInfo(Path.Combine(_Dir.FullName, "ViewState")); if (!_Dir.Exists) _Dir.Create(); } return _Dir; } } protected override object LoadPageStateFromPersistenceMedium() { PageStatePersister ps = this.PageStatePersister; ps.Load(); if (ps.ControlState != null) ps.ControlState = 反序列化对象((string)ps.ControlState); if (ps.ViewState != null) ps.ViewState = 反序列化对象((string)ps.ViewState); return new Pair(ps.ControlState, ps.ViewState); } protected override void SavePageStateToPersistenceMedium(object state) { PageStatePersister ps = this.PageStatePersister; if (state is Pair) { Pair pair = (Pair)state; ps.ControlState = pair.First; ps.ViewState = pair.Second; } else { ps.ViewState = state; } if (ps.ControlState != null) ps.ControlState = 序列化对象(ps.ControlState); if (ps.ViewState != null) ps.ViewState = 序列化对象(ps.ViewState); ps.Save(); } private object 反序列化对象(string stateID) { string stateStr = (string)Cache[stateID]; string file = Path.Combine(Dir.FullName, stateID); if (stateStr == null) stateStr = File.ReadAllText(file); else Cache.Remove(stateID); return new ObjectStateFormatter().Deserialize(stateStr); } private string 序列化对象(object obj) { string value = new ObjectStateFormatter().Serialize(obj); string stateID = (DateTime.Now.Ticks + (long)value.GetHashCode()).ToString(); //产生离散的id号码 File.WriteAllText(Path.Combine(Dir.FullName, stateID), value); Cache.Insert(stateID, value); return stateID; } protected override void OnUnload(EventArgs e) { base.OnUnload(e); DateTime dt = DateTime.Now.AddMinutes(-20); foreach (FileInfo fl in Dir.GetFiles()) if (fl.LastAccessTime < dt) try { fl.Delete(); } catch { } }}
------解决方案--------------------------------------------------------
你不会是仅仅为了在string与byte[]之间转换就动用了Base64编码解码功能了吧?在调用compressedData = CH.Compress(data);前后,都无需Base64解码和编码,直接把compressedData 从byte[]转换为string就可以了(无需编码)。