Pages

Saturday, February 23, 2013

How to download file using handler

Here is a detailed description on How to download file using handler. Also some tips on RadUpload custom validation.
You can use a generic handler to download files from server, it has the following advantages:
1. You can have download statistics.
2. You can track downloads.
3. You can implement download protection by putting extra authentication.
4 Download can be disallowed if required.
Lets say you have a RadUpload control on your page.

<telerik:RadUpload ID="rup_AttachedFiles" runat="server" ControlObjectsVisibility="RemoveButtons, AddButton" />

And you want to validate the files on the client side which are being uploaded,
so add a custom validator:

<asp:customvalidator id="CustomValidator1" runat="server" validationgroup="frmInquiry" enabled="true" clientvalidationfunction="ValidateFileNames" errormessage="Please Upload a file or same file is being uploaded twice" text="*" display="None" />

Now you write the Client Validation Function for your custom validator:

<script type="text/javascript">
    function ValidateFileNames(Source, args) {
        var FilesValid = true;
        var AttachedFiles = new Array();
        var radUpload = $find('<%= rup_AttachedFiles.ClientID %>');
        var fileInputs = radUpload.getFileInputs();
        if ((fileInputs.length == 1) && (fileInputs[0].value == "")) {
            FilesValid = false;
        }
        else {
            var duplicateFieldFlag = false;
            for (var i = 0; i < fileInputs.length; i++) {
                var fileName = fileInputs[i].value.substring(fileInputs[i].value.lastIndexOf("\\") + 1, fileInputs[i].value.length);
                for (var j = 0; j < AttachedFiles.length; j++) {
                    if (fileName == AttachedFiles[j]) {
                        duplicateFieldFlag = true;
                        radUpload.clearFileInputAt(i);
                        fileInputs[i].focus();
                        break;
                    }
                }
                if (duplicateFieldFlag) {
                    FilesValid = false;
                    break;
                }
                if (fileInputs[i].value.length != 0) {
                    AttachedFiles[AttachedFiles.length] = fileName;
                }
            }
        }
        args.IsValid = FilesValid;

    }
</script>

I am not going into detail of how to upload it using RadUpload control. Its time to put a repeater control to show a list of already uploaded files from the server. Again I will not explain how to get the uploaded files information from DB and bind it to the repeater.

<asp:repeater id="rpAttach" runat="server" 
onitemdatabound="rpAttach_onItemDataBound">
    <HeaderTemplate>
       <table id="tbl1" cellpadding="0" cellspacing="0" border="0" width="100%">
         <tr>
          <td>
           <asp:Label runat="server" ID="lblAttachement" Text="File Name" />
          </td>
        </tr>
    </HeaderTemplate>
    <ItemTemplate>
      <tr>
       <td >
        <asp:LinkButton ID="lnkFileName" runat="server" ></asp:LinkButton>
       </td>
      </tr>
    </ItemTemplate>
    <SeparatorTemplate>
        <tr>
            <td>
                <hr />
            </td>
        </tr>
    </SeparatorTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
    </asp:repeater>

Now you have to define the event handler rpAttach_onItemDataBound for the event OnItemDataBound. Where you will bind the file name link to a javascript function. Which will show a Disclaimer text before downloading:

protected void rpAttach_onItemDataBound(object
    sender, RepeaterItemEventArgs e) 
    { 
        if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item) 
        { 
            LinkButton aLinkFileName = (LinkButton)e.Item.FindControl("lnkFileName");
            Files sFile = ((Files)e.Item.DataItem); aLinkFileName.Text = sFile.FileName; aLinkFileName.Attributes.Add("OnClick","OpenDisclaimer('" + HttpUtility.UrlEncode(strBasePath) + "','" + HttpUtility.UrlEncode(sFile.FileName)+ "','" + ConfigurationManager.AppSettings["DisclaimerText"] + "')"); 
        } 
    } 

Now put the disclaimer text in the web config file

<add key="DisclaimerText" value="The attachment contains confidential and proprietary information. You have abide by copyright laws. blah blah blah " />

Now we have to define the function OpenDisclaimer

<script type="text/javascript">
        function OpenDisclaimer(strFilePath, strFileName, strText) {
            strURL = 'Handlers/GetFile.ashx?FullPath=' + strFilePath + '&FileName=' + strFileName;
            var answer = confirm("Disclaimer: " + strText);
            if (answer) {
                window.location.href = strURL;
                return true;
            }
            else 
            return false;
        } 
    </script>

Now is the time to add the GetFile handler to your project. Below is the code for it. It recognizes the file type and puts the contents of file type into chunks by chunks to client. // Handlers/GetFile.ashx

<%@  WebHandler Language="C#" Class="GetFile" %>

    using System; 
    using System.Collections; 
    using System.Data; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Services; 
    using System.Web.Services.Protocols; 
    using System.Xml.Linq; 
    using System.IO; 
    using System.Web.SessionState; 
    using System.Configuration;

    [WebService(Namespace = "http://tempuri.org/")] 
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 

    public class GetFile : IHttpHandler, IReadOnlySessionState
    { 
        public void ProcessRequest(HttpContext context) 
        { 
            try 
            { 
                string FilePath = context.Request.Params["FullPath"];
                string filename = context.Request.Params["FileName"]; 

                FilePath = HttpUtility.UrlDecode(FilePath);
                string fullPath = "\\FileServername\FolderName\" + FilePath + filename; 

                // "\\FileServername\FolderName\" you can keep this path in web config string extension = System.IO.Path.GetExtension(filename);

                if (extension == null) 
                    extension = ""; 
                extension = extension.Replace(".", "");

                string contentDisposition; 

                if (context.Request.Browser.Browser == "IE" && (context.Request.Browser.Version == "7.0" || context.Request.Browser.Version == "8.0")) 
                    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(filename); 
                else if (context.Request.Browser.Browser == "Safari") 
                    contentDisposition = "attachment; filename=" + filename; 
                else 
                    contentDisposition= "attachment; filename*=UTF-8''" + Uri.EscapeDataString(filename); 
        
                context.Response.AddHeader("Content-Disposition",contentDisposition); 
                context.Response.ContentType = "Application/" + extension;

                System.IO.BinaryReader reader = new System.IO.BinaryReader(new System.IO.FileStream(fullPath,System.IO.FileMode.Open)); 
        
                //Sent the data in chunks of x byte int ChunkSize = 10000;
                byte[] buffer = new byte[ChunkSize]; 
                int idx = 0; 
                long size = 0; 
        
                //Write the file chunk by chunk. 
        
                while ((size = reader.Read(buffer, 0, ChunkSize)) == ChunkSize)
                { 
                    context.Response.BinaryWrite(buffer); 
                    idx += ChunkSize; 
                } 
        
                reader.Close(); 
        
                //Write the remaining bytes 
                if (size > 0) 
                { 
                    byte[] remaining = new byte[size]; Array.Copy(buffer, 0, remaining, 0, size); 
                    context.Response.BinaryWrite(remaining); 
                } 
            } 
            catch 
            { 
                context.Response.ContentType= "Application/html"; 
                context.Response.StatusCode = 404; 
                context.Response.StatusDescription = "File not found"; 
            } 
        } 
    } 

Enjoyyyyyy!!!!

No comments: