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.com\files\hello.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
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"]);
}