skip to Main Content

I have a website users can create files that are stored for them as PDF’s. I want to block direct access to those files for the general user but still allow direct access for the admin. So that random users cannot just type in something like www.website.com/files/hello.pdf and gain access to any user’s files. But I want the admin to be able to access that file.

I have tried Hidden segments in IIS but that blocks the entire folder for everyone, including the admin. I have tried to figure out how to use request filtering rules but I just can’t seem to get it right.

A user’s role is stored as a Session[]. if that session is "userA" role then they are a general user and I do not want them to have direct access to the file. But if that session is "userB" role then they are an admin and I want them to have direct access to the file. e.g. www.website.comfileshello.pdf

My other issue is that the PDF Files are within a GridView, so more than one file will be embedded into multiple rows. I have figured out how to embed the PDF into the ASPX by converting the PDF Info to Base64 and then inserting that data into the source of the embed tag. The issue now is that this is some heavy lifting for the browser when loading more than 10 rows from the GridView. So it works but I imagine there is a more memory-efficient way of doing this.

This is what I did so far

<embed src='<%# Eval("pdfBytes")%>' type="application/pdf" width="910px" height="1100px"/>

 string FilePath = Server.MapPath(FileLocation);
                            WebClient User = new WebClient();
                            Byte[] FileBuffer = User.DownloadData((FilePath));
                            if (FileBuffer != null)
                            {
                                
                                base64PDF = "data:application/pdf;base64, " + System.Convert.ToBase64String(FileBuffer, 0, FileBuffer.Length);

                                dt.Rows[i]["pdfBytes"] = base64PDF + "  #>";


                            }


                        }

Any thoughts on how I can do this? Please help

2

Answers


  1. Chosen as BEST ANSWER

    I could not find a clear answer on the web but with a lot of this communities help I was able to put this together as an answer to my problem.

    On the ASPX where I have my GridView I placed this code

    <iframe id="iframePDF" runat="server"  width="910px" height="1100px" scrolling="no" frameborder="0" ></iframe>
    

    In the ASPX.CS where I have my Gridview I filled the GridView from SQL and placed these codes into the GridViewRowEventHandler.

    if (e.Row.RowType == DataControlRowType.DataRow)
            {
    
                using (SqlConnection con = new SqlConnection(strcon))
                {
                    if (con.State == ConnectionState.Closed)
    
                    {
                        con.Open();
                    }
    
                    Label flagID = (Label)e.Row.FindControl("ID");
                    
    
                    SqlCommand cmd = new SqlCommand("COMMAND ", con);
    
                    cmd.CommandType = CommandType.Text;
                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    da.Fill(dt);
    
                    if (dt.Rows.Count >= 1)
                    {
    
                        System.Web.UI.HtmlControls.HtmlIframe Iframe = (System.Web.UI.HtmlControls.HtmlIframe)e.Row.FindControl("IFRAMEID");
    
                        Iframe .Attributes["src"] = "fileViewer.aspx?Location=" + dt.Rows[0]["FileLocation"].ToString();
                    }
                    }
     }
    

    Then in the FileViewer.ASPX I put an IFrame where the PDF will be viewed I pulled the SRC from the Query String I attached to the URL

     <iframe width="910px" height="1100px" scrolling="no" frameborder="0" id="iframe"></iframe>
    

    and in the FileViewer.ASPX.CS I placed the below code to fill the SRC of this new IFrame. I run this on page load.

     void FileLoader()
        {
            Response.ContentType = "application/pdf";
            Response.AppendHeader("Content-disposition", "inline; filename=" + "PDFFile");
            string test = Request.QueryString["Location"];
            Response.TransmitFile(Request.QueryString["Location"]);
        }
    

  2. This is the steps that you have to follow.

    1. You save your files under App_Data directory, that is inaccessible from any user. Only pool can access any data there, so you can save and read there on code behind, but not direct access it by any url
    2. You create a handler thats returns that file (base on some parameter that you send on url) if your user have this role.

    eg, you create a download.ashx, make the checks if the user have the roles and its authenticated, add the correct headers and content type, disable the cache…

    context.Response.ContentType = "application/pdf";
    context.Response.AppendHeader("Content-disposition", "attachment; filename=" + FullFileName);   
    

    and add some code to read and send the protected file to Response Output Stream.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search