<requestFiltering>
<hiddenSegments>
<add segment="Test"/>
</hiddenSegments>
</requestFiltering>
I have web site (ASP.Net web form) with above code in web.config to prevent direct access to Test folder files, some times I want to access images inside my site from Test folder is there any way to exclude this feature to read files.
For example
when user access web site i want to display images related to him as thumbnail, when I add image source to that physical file inside Test folder the website can't read file.
Note: I can Download files inside Test Folder to user without any issue.
Is there any way to read files content without download whole file?
Thanks
CodePudding user response:
You can use code behind to display the file(s) in question.
Remember: Code behind: any file reference is a FULL plane jane file path name.
WEB: controls and web URL's: they are controlled by your web config security.
So, say we had a folder with some pictures. We secure that folder with web config. Now all users can't use, see, type in that URL. But, you can STILL use code behind and as noted, they are plane jane full windows path names. So, just keep in mind this "major" difference between code behind, and that of web pages and using web.config security.
So, you can say have a gridview, and display images in that grid, but the URL's to the pictures would NOT be valid - we simple use code behind to read the picture file and "stream" it to the browser.
This setup (say a grid) will thus look like this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" width="65%" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" ItemStyle-Width="160px" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust (lbs)" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Image">
<ItemTemplate>
<asp:ImageButton ID="cmdImage" runat="server" Height="78px" Width="132px" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
and code to load grid looks like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * FROM Fighters ORDER BY Fighter", conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
' get data row for grid
Dim gData As DataRowView = e.Row.DataItem
Dim ImageURL As String =
Server.MapPath(gData("ImagePath")) ' get raw windows path name
Dim cmdImage As ImageButton = e.Row.FindControl("cmdImage")
Dim iBytes() As Byte
iBytes = File.ReadAllBytes(ImageURL)
cmdImage.ImageUrl = "Data:Image/jpg;base64," & Convert.ToBase64String(iBytes)
End If
End Sub
And we now have this:
So remember that code behind can go read files directly from those folders - it quite much "ignores" the web config and security you apply against a web url or folder when you use code behind. Thus, for say PDF's, or images you want to display, but not allow direct URL's to the folder? Use code behind - all code behind uses full simple plane jane windows path names. You can convert the path name from the folder (and url) with Server.MapPath("some web url goes here").
Once you convert to that internal path name - then your code behind is free to get/grab/use that file - it quite much ignores the web config settings.
So, in above, i had/have a column in the database with path names to the images - but I don't have to expose that column into the GridView, and users can't see, or type in valid URL's to that folder with pictures - since I prevented them from doing so with the web.config settings for that folder.
Edit: Downloading the file when user clicks on the image
So, what about allowing the user to download the file when you click on the image button?
Well, we just need to wire up a simple click event for that button.
We can't double click on the button to get that code behind click event, (since it inside of the grid). But you can start typing in the markup like this:
Choose create new event - it LOOKS like nothing occurs, but if we flip to code behind, you see the image button click event was created.
When the user click on that button, we will download the file.
That code can look like this:
Protected Sub cmdImage_Click(sender As Object, e As ImageClickEventArgs)
Dim cmdImage As ImageButton = sender
Dim gRow As GridViewRow = cmdImage.NamingContainer
Dim PkRowID As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
Dim strSQL As String =
"SELECT ID,ImagePath FROM Fighters WHERE ID = " & PkRowID
Dim strPicPath As String = ""
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
strPicPath = rstData.Rows(0).Item("ImagePath")
strPicPath = Server.MapPath(strPicPath)
End Using
End Using
Dim strPicFile = Path.GetFileName(strPicPath)
Dim iBytes() As Byte = File.ReadAllBytes(strPicPath)
Response.ClearHeaders()
Response.AddHeader("content-disposition", "attachment;filename=" & strPicFile)
Response.BinaryWrite(iBytes)
Response.Flush()
Response.End()
End Sub