Crystal Report Viewer(Asp.NET) 無法Download PrintControl.cab問題
前言
依上篇「建立共用的Asp.NET Crystal Report 2008 Viewer程式!」中,因為印表的方式是使用ActiveX方式,所以會Download PrintControl ActiveX到Client去印表! 但是有些Report可以Download, 有些卻不行!
研究
發現不可以download的情形是在download的畫面上會出現「發行者:發行者不明」,按下安裝後,就動也不動。
而可以download的情形在download的畫面上則會出現「發行者:Business Objects Americas」,如下圖!
應該是URL有問題吧!
看一下那個printControl.cab之前居然有/,如下圖!
CRViewer.aspx?aZ8JMRWR2YxLwZ327aUlK9uVqPC4wivWDSowQ8mCmurrCyLSkxIGXTfplnHRq/9vwis0MsC7A/gb22QQGj2emqFCRcRwC03e9lrOCFRnba@@@VmROgtCXeRTzJ89WZ2/ayY3XFNFJETdvgeLYbMsS8wVx8dhkKW6cnvjomGVPY/../aspnet_client/system_web/2_0_50727/crystalreportviewers12/ActiveXControls/PrintControl.cab
所以就修正StringHelper的加解密Function,將/改以3個$替換後,就可以正常Download了!
//因為要列印時,前面不能有/會造成download PrintControl.cab錯誤 return Convert.ToBase64String(bytOut).Replace("+", "@@@").Replace(@"/", "$$$");
byte[] bytIn = Convert.FromBase64String(encryptedString.Replace("@@@", "+").Replace("$$$", @"/"));
完整的function如下,
using System.Data; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.Security.Cryptography; using System.Collections.Specialized; using System.Text; using System.IO; /// <summary> /// 加解密字串 /// </summary> /// <remarks> /// 改自網路,加入自定Key值加解密及錯誤處理 /// </remarks> public class StringHelpers { public const char QUERY_STRING_DELIMITER = '&'; private static RijndaelManaged _cryptoProvider; //128 bit encyption: DO NOT CHANGE private static readonly byte[] Key = { 18, 19, 8, 24, 8, 22, 2, 25, 17, 5, 11, 9, 13, 15, 06, 9 }; private static readonly byte[] IV = { 14, 2, 16, 7, 5, 9, 33, 23, 23, 47, 16, 12, 1, 32, 25, 9 }; static StringHelpers() { _cryptoProvider = new RijndaelManaged(); _cryptoProvider.Mode = CipherMode.CBC; _cryptoProvider.Padding = PaddingMode.PKCS7; } public static string Encrypt(string unencryptedString) { return Encrypt(unencryptedString, string.Empty); } public static string Encrypt(string unencryptedString, string myKey) { //byte[] bytIn = ASCIIEncoding.ASCII.GetBytes(unencryptedString); //如果內容有unicode的話,要用utf8編碼 byte[] bytIn = UTF8Encoding.UTF8.GetBytes(unencryptedString); byte[] bytKey; if(string.IsNullOrEmpty(myKey)){ bytKey = Key; }else{ bytKey = ASCIIEncoding.ASCII.GetBytes(myKey); Array.Resize(ref bytKey, 16); } // Create a MemoryStream MemoryStream ms = new MemoryStream(); // Create Crypto Stream that encrypts a stream CryptoStream cs = new CryptoStream(ms, _cryptoProvider.CreateEncryptor(bytKey, IV), CryptoStreamMode.Write); // Write content into MemoryStream cs.Write(bytIn, 0, bytIn.Length); cs.FlushFinalBlock(); byte[] bytOut = ms.ToArray(); //因為url不能吃+所以要轉成@@@ //因為要列印時,前面不能有/會造成download PrintControl.cab錯誤 return Convert.ToBase64String(bytOut).Replace("+", "@@@").Replace(@"/", "$$$"); } public static string Decrypt(string encryptedString) { return Decrypt(encryptedString, string.Empty); } public static string Decrypt(string encryptedString, string myKey) { if (encryptedString.Trim().Length != 0) { //如果有人改加密字串的話,解就會發生錯誤,所以錯誤就回傳空字串 try { // Convert from Base64 to binary 在解開前要先將@@@轉成+,將$$$轉成/ byte[] bytIn = Convert.FromBase64String(encryptedString.Replace("@@@", "+").Replace("$$$", @"/")); byte[] bytKey; if(string.IsNullOrEmpty(myKey)){ bytKey = Key; }else{ bytKey = ASCIIEncoding.ASCII.GetBytes(myKey); Array.Resize(ref bytKey, 16); } // Create a MemoryStream MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length); // Create a CryptoStream that decrypts the data CryptoStream cs = new CryptoStream(ms, _cryptoProvider.CreateDecryptor(bytKey, IV), CryptoStreamMode.Read); // Read the Crypto Stream StreamReader sr = new StreamReader(cs); return sr.ReadToEnd(); } catch { return ""; } } else { return ""; } } public static NameValueCollection DecryptQueryString(string queryString) { return DecryptQueryString(queryString, string.Empty); } public static NameValueCollection DecryptQueryString(string queryString, string myKey) { if (queryString.Length != 0) { //Decode the string string decodedQueryString = HttpUtility.UrlDecode(queryString); //Decrypt the string string decryptedQueryString = StringHelpers.Decrypt(decodedQueryString, myKey ); //Now split the string based on each parameter string[] actionQueryString = decryptedQueryString.Split(new char[] { QUERY_STRING_DELIMITER }); NameValueCollection newQueryString = new NameValueCollection(); //loop around for each name value pair. for (int index = 0; index < actionQueryString.Length; index++) { string[] queryStringItem = actionQueryString[index].Split(new char[] { '=' }); if(queryStringItem.Length > 1) newQueryString.Add(queryStringItem[0], queryStringItem[1]); } return newQueryString; } else { //No query string was passed in. return null; } } public static string EncryptQueryString(NameValueCollection queryString) { return EncryptQueryString(queryString, string.Empty); } public static string EncryptQueryString(NameValueCollection queryString, string myKey) { //create a string for each value in the query string passed in. string tempQueryString = ""; for (int index = 0; index < queryString.Count; index++) { tempQueryString += queryString.GetKey(index) + "=" + queryString[index]; if (index != queryString.Count - 1) { tempQueryString += QUERY_STRING_DELIMITER; } } return EncryptQueryString(tempQueryString, myKey); } public static string EncryptQueryString(string queryString) { return EncryptQueryString(queryString, string.Empty); } public static string EncryptQueryString(string queryString, string myKey) { return "?" + HttpUtility.UrlEncode(StringHelpers.Encrypt(queryString, myKey)); } }
沒想到URL的QueryString也會影響到download呀~!
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^