Harikrishna
Harikrishna

Reputation: 4305

File Content viewer on browser using asp.net

How to view content of uploaded files on browser in asp.net ? And is it possible to view contents of all type of files using common code ? Or there is any free project there ?

Thanks..

Upvotes: 1

Views: 5493

Answers (2)

competent_tech
competent_tech

Reputation: 44971

In order to allow the user to view the files inline, you will need to stream the file to the user and set some values in the header.

We usually perform this action using an HTTP handler mapped to a "virtual" page (i.e. Download.aspx) so that it can be called from the client side in a popup window without affecting the calling page.

This mechanism can be used to either download or view a file inline.

Here is a description of the download process implemented in the StreamFileToUser method in the class at the end of this answer:

If the caller requests a download, then we check a collection of mime types to determine whether or not the file contains a supported mimetype, which means that it has a chance of being displayed inline to the user.

If the mime type is found, we use the inline directive to ask the browser to show the file to the user. If the browser doesn't support inlining for this mime type, the user will be prompted to download.

If we don't find a mime type, then a straight download command will be issued.

You can get the complete list of mime types within IIS (assuming 7+) by opening IIS manager, selecting the web server icon, and double-clicking the Mime Types icon.

Here is an example of the HTTP handler class:

public class DownloadRequestHandler : System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    /// <summary>
    /// This method is used to process the incoming request
    /// </summary>
    /// <param name="oContext"></param>
    /// <remarks></remarks>
    public void ProcessRequest(HttpContext oContext)
    {
        try
        {
            string sFileName = null;
            string sSourceFilePath = null;

            // Should add existence checking here
            sFileName = oContext.Request.QueryString["FileName"];

            // Assume that the files are stored in the relative directory Files. Should add existence checking here
            sSourceFilePath = System.IO.Path.Combine(oContext.Server.MapPath("Files"), sFileName);

            StreamFileToUser(GenerateStandardMimeList(), sSourceFilePath, sFileName, oContext.Response, false, false);
        }
        catch (System.Threading.ThreadAbortException theException)
        {
            // Do nothing
        }
        catch (Exception theException)
        {
            SendErrorToUser(oContext.Response, theException.Message);
        }
    }
    /// <summary>
    /// This method streams a file to a user
    /// </summary>
    /// <param name="cMimeTypes">The set of known mimetypes. This is only needed when the file is not being downloaded.</param>
    /// <param name="sFileName"></param>
    /// <param name="sFileNameForUser"></param>
    /// <param name="theResponse"></param>
    /// <param name="fDownload"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public bool StreamFileToUser(System.Collections.Generic.Dictionary<string, string> cMimeTypes, string sFileName, string sFileNameForUser, HttpResponse theResponse, bool fDownload = true, bool fOkToDeleteFile = false)
    {
        // Exceptions are handled by the caller

        bool fDontEndResponse = false;

        sFileNameForUser = CleanFileName(sFileNameForUser);

        // Ensure there is nothing else in the response
        try
        {
            try
            {
                // Remove what other controls may have been put on the page
                theResponse.ClearContent();
                // Clear any headers
                theResponse.ClearHeaders();
            }
            catch (System.Web.HttpException theException)
            {
                // Ignore this exception, which could occur if there were no HTTP headers in the response
            }

            bool fFoundIt = false;

            if (!fDownload)
            {
                string sExtension = null;

                sExtension = System.IO.Path.GetExtension(sFileNameForUser);
                if (!(string.IsNullOrEmpty(sExtension)))
                {
                    sExtension = sExtension.Replace(".", "");
                    if (cMimeTypes.ContainsKey(sExtension))
                    {
                        theResponse.ContentType = cMimeTypes[sExtension];
                        theResponse.AddHeader("Content-Disposition", "inline; filename=" + sFileNameForUser);
                        fFoundIt = true;
                    }
                }
            }

            if (!fFoundIt)
            {
                theResponse.ContentType = "application/octet-stream";
                theResponse.AddHeader("Content-Disposition", "attachment; filename=" + sFileNameForUser);
            }

            theResponse.TransmitFile(sFileName);

            // Ensure the file is properly flushed to the user
            theResponse.Flush();
        }
        finally
        {
            // If the caller wants, delete the file before the response is terminated
            if (fOkToDeleteFile)
            {
                System.IO.File.Delete(sFileName);
            }
        }

        // Ensure the response is closed
        theResponse.Close();

        if (!fDontEndResponse)
        {
            try
            {
                theResponse.End();
            }
            catch
            {
            }
        }

        return true;
    }

    /// <summary>
    /// This method generates a standard list of extension to content-disposition tags
    /// The key for each item is the file extension without the leading period. The value 
    /// is the content-disposition.
    /// </summary>
    /// <returns></returns>
    /// <remarks></remarks>
    public System.Collections.Generic.Dictionary<string, string> GenerateStandardMimeList()
    {
        // Exceptions are handled by the caller.

        System.Collections.Generic.Dictionary<string, string> cItems = new Dictionary<string, string>();

        cItems.Add("jpeg", "image/jpeg");
        cItems.Add("jpg", "image/jpeg");
        cItems.Add("pdf", "application/pdf");
        cItems.Add("csv", "application/vnd.ms-excel");
        cItems.Add("doc", "application/msword");
        cItems.Add("docx", "application/vnd.ms-word.document.12");
        cItems.Add("xls", "application/vnd.ms-excel");
        cItems.Add("xlsx", "application/vnd.ms-excel.12");

        return cItems;
    }

    /// <summary>
    /// This method removes all invalid characters from the specified file name.
    /// Note that ONLY the file name should be passed, not the directory name.
    /// </summary>
    /// <param name="sFileName"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public string CleanFileName(string sFileName)
    {
        // Exceptions are handled by the caller

        // If there are any invalid characters in the file name
        if (sFileName.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) >= 0)
        {
            // Strip them out (split to remove the characters, then rejoin the pieces into one string)
            return string.Join("", sFileName.Split(System.IO.Path.GetInvalidFileNameChars()));
        }
        else
        {
            return sFileName;
        }
    }

    public void SendErrorToUser(HttpResponse theResponse, string sError)
    {
        // Note that errors are handled by the caller

        sError = "<script>alert(\"" + sError.Replace("\"", "").Replace(Environment.NewLine, "\\n") + "\");</script>";
        // Ensure there is nothing else in the response
        theResponse.Clear();
        theResponse.Write(sError);
        theResponse.Flush();
    }
}

In your web.config, add the following line to the httphandlers section, replacing the namespace as appropriate:

    <add path="download.aspx" verb="*" type="MyWebApp.DownloadRequestHandler, MyWebApp" validate="false" />

Then your download request is:

download.aspx?FileName=thefile.pdf

and the above code assumes that the files are stored in the Files subdirectory of the website.

Upvotes: 0

Icarus
Icarus

Reputation: 63970

You won't be able to see the content of any file as that would require the browser in question to have a plugin to display a particular file. Take for example a MS Project File, a Corel Draw File an Auto CAD, what have you. The browser won't display those since AFAIK, there's not a plugin provided for these files that can be used by the browser to embed a viewer in it.

The browser, in general, will happily display PDFs (provided Acrobat Reader is installed), Images, TXT files and a couple others.

Therefore, you can perfectly read all the files doing something like:

DirectoryInfo info = new DirectoryInfo("PhysicalPathToFiles");
GridView1.DataSource=info.GetFiles();
GridView1.DataBind();

And set up your GrdiView1 markup to only bind the FileName property and everything else you need. You'd want to construct a hyperlink on this column so that when the file name is clicked, the user is asked to download/view the file, depending on the file type.

Let's say you bound all the files to the Gridview as I explained above. Having a GridViewColumn like this, should allow the user to click on any file and see it inside the browser.

<asp:HyperLinkColumn
                 HeaderText="File Name"
                 DataNavigateUrlField="Name"
                 DataNavigateUrlFormatString="UploadedFiles/{0}"
                 DataTextField="Name"
                 />

Where UploadedFiles is the virtual directory inside your app that holds these files.

Upvotes: 2

Related Questions