A friend of mine asked me today about encoding a string Base64. The scenario was that he has some files that he wants to be allowed for download on their company website and that he doesn't want the people who are downloading the files from his website to see where the downloads are coming from. The files are located in a folder inside the webserver outside of the virtual directory. The decision that the came up with was just to Base64 encode all the paths, pass ito to a new page via querystring and then decode that value on the download page. I gave it a shot and this is the code i gave him to serve as a guide on how he can effectively implement this.
First, we formatted the ItemTemplates of our datagrid in our default.aspx page:
<asp:DataGrid id="fileGrid" runat="server" AutoGenerateColumns="False"> <Columns> <asp:TemplateColumn> <ItemTemplate> <asp:HyperLink runat="server" Text="Get" NavigateUrl='<%# HttpEncodeFilePath(DataBinder.Eval(Container, "DataItem.FullName")) %>' Target="_self"> </asp:HyperLink> </ItemTemplate> </asp:TemplateColumn> <asp:BoundColumn DataField="Name" HeaderText="Filename"></asp:BoundColumn> <asp:BoundColumn DataField="FullName" HeaderText="Full Path"></asp:BoundColumn> </Columns></asp:DataGrid>
The reason why we formatted the grid this way is that because we would be binding the contents of a FileInfo[] to our grid.
The next thing that we need to do is setup the events inside our default.aspx page. The listing below shows the code that we used for this page:
using System;using System.IO;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;namespace KeithRull.Web.EncryptPath{ /// <summary> /// Encoding a string. /// </summary> public class defaultpage : System.Web.UI.Page { protected System.Web.UI.WebControls.DataGrid fileGrid; private void Page_Load(object sender, System.EventArgs e) { //check if the request is not a postback if(!IsPostBack) { //assign the fileinfo[] to our grid fileGrid.DataSource = LoadFileSystem(); //bind it to our grid fileGrid.DataBind(); } } /// <summary> /// Gets the contents of our filesystem /// </summary> /// <returns>an array of fileinfo</returns> private FileInfo[] LoadFileSystem() { //create our directoryinfo and set its working folder to c:\Windows DirectoryInfo dInfo = new DirectoryInfo(@"c:\Windows"); //return the files in the directory that matches our filter return dInfo.GetFiles("*.txt"); } /// <summary> /// A function that returns the Base64 encoded path /// </summary> /// <param name="filePath">the file location</param> /// <returns>the base64 encoded file path</returns> protected string HttpEncodeFilePath(object filePath) { //variable to hold our path string fp = filePath as string; //variable to olde our byte array string b64 = Convert.ToBase64String(StrToByteArray(fp)); //return the formatted base64 string return string.Format("download.aspx?file={0}",HttpUtility.UrlEncode(b64)); } /// <summary> /// convert a string to a byte array. /// </summary> /// <param name="str">a string to convert to bytes</param> /// <returns>the byte[] containing our string</returns> public static byte[] StrToByteArray(string str) { //create our encoder System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding(); //the byte[] containing our string return encoding.GetBytes(str); } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion }}
The last part is setting up the download.aspx page which would accept our query string. For simplicity, we have omitted the download procedure and instead we just show the decoded string to the user.
using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;namespace KeithRull.Web.EncryptPath{ /// <summary> /// Decoding a Base64 string. /// </summary> public class download : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { // Check if the page Is not a PostBack if(!IsPostBack) { //Validate if the querystring is null if(Request.QueryString["file"]== null) { //redirect to the main page Response.Redirect("default.aspx"); } //Get the value of our querystring string filePath = HttpDecodeFilePath(Request.QueryString["file"]); //output the decoded string to the page Response.Write(filePath); } } /// <summary> /// A function used to decode our filepath /// </summary> /// <param name="filePath">the Base64 string</param> /// <returns>the decoded value</returns> protected string HttpDecodeFilePath(object filePath) { //Get the value of our filepath and URL Decode it string fp = HttpUtility.UrlDecode(filePath as string); //Convert our string back to Base64 byte[] b64 = Convert.FromBase64String(fp); //return a Base64 string return string.Format("{0}",ByteToStringArray(b64)); } /// <summary> /// convert a string to a byte array. /// </summary> /// <param name="byteStr">our byte string</param> /// <returns>the decoded base64 string</returns> public static string ByteToStringArray(byte[] byteStr) { //Create our encoder System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); //return our decoded string return enc.GetString(byteStr); } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion }}
And there you have it. The filepath can now be pased to the download.aspx page from our default.aspx page in the form of a base64 string and then decoded back to its original state when the download.aspx page is loaded. This application is just a simple example and can be improve by using HttpHandlers instead of using the download.aspx page. Or we can implement URL re-writing instead. The focus of this demo is plainly for showing how to base64 encode strings and decoded it on the other end.
You can download the full source code of the application here: KeithRull.Web.EncryptPath.zip (15.17 KB)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.