:: Professional ::
 
You are here: Blog
 

Hilbert Solutions, LLC Latest Dotnetnuke Modules...

Advanced News Ticker        Constant Contact Sign Up

 

Blog
Apr21

Written by:slhilbert
4/21/2009 10:40 AM 

As web developers we are often creating ways for people to upload files.  Usually uploading a file is pretty trivial and there are numerous examples of how to do it across the Internet.  From time to time we have the need to secure the file we are uploading, to prevent someone from directly navigating to the file and downloading it without our permission.  It is at these times that we have to modify the file upload process just a bit in order to prevent direct access to our files.  Of course, we still need to be able to use the files that are uploaded, so this walkthrough will show you how to upload and secure your files and also how to download your secured files. 

The premise of our security is that files with the file extension of “.resource” are not served by web servers, at least not by IIS.  Therefore all we have to do is add the file extension of “.resource” to any file we upload.  If we uploaded a file named, “Gnome.jpg”, we would store it on the server as “Gnome.jpg.resource”.  If someone were to try to navigate directly to the URL associated with the “Gnome.jpg.resource” they wouldn’t be able to pull up the image.

When we download the file we simply rename the file back to “Gnome.jpg” and start the download.  In order for this to make sense you will need a way to secure who has access to download the file. I usually do that based on Roles in Dotnetnuke, but you can do it anyway you want.

THE ASCX OR ASPX CODE

First let’s look at the .ACSX or the .ASPX code (depending on what you are using).

 <INPUT id="fuFuncATTACHMENTSFile" type="file" size="20" name="fuFuncATTACHMENTSFile" class="CommandButton" runat="server" style="height: 1.75em; width: 210px;">&nbsp;
<asp:Button id="btnFuncATTACHMENTUpload" runat="server" CssClass="CommandButton" Width="67px" Text="Add File" CausesValidation="False"></asp:Button>

Above is your standard input box used to select file attachments.  I would point out that the ASP:Button has the "CausesValidation” property set to FALSE in order to prevent any valuators on the rest of your form from firing during the file selection process.

 

THE UPLOAD CODE

When the ASP:Button, “btnFuncATTACHMENTUpload” is clicked the following code is fired:

Protected Sub btnFuncATTACHMENTUpload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFuncATTACHMENTUpload.Click
 'Grab the file name from its fully qualified path at client 
 Dim strFileName As String = fuFuncATTACHMENTSFile.PostedFile.FileName
 ' only the attched file name not its path
 Dim c As String = System.IO.Path.GetFileName(strFileName)
 'Save uploaded file to server 
 'Storing the file name
 Dim arrFileName As String()
 'Getting just the file name
                    arrFileName = strFileName.Split(Convert.ToChar("\"))
 'Saving the attachment
                    fuFuncATTACHMENTSFile.PostedFile.SaveAs("c:\inetpub\DNNTest\FileStore\" & strFileName & ".resource") 'adding .resource for security
End Sub

 

THE CODE FOR DOWNLOADING

Protected Sub imgFuncDocumentsView_Click(ByVal sender As System.Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles imgFuncDocumentsView.Click
'replace STOREDFILENAMEwithRESOURCE with the name of the secure file, which would include the .resource extension
'replace ORIGINALFILENAME with the original name of the file or some other name that you want to appear when downloading.
'Calling procedure StreamFile
    StreamFile("c:\inetpub\DNntest\FileStore\" & STOREDFILENAMEwithRESOURCE & ".resource",ORIGINALFILENAME)
End Sub
Private Sub StreamFile(ByVal FilePath As String, ByVal DownloadAs As String)
            DownloadAs = DownloadAs.Replace(" ", "_")
 Dim objFile As New System.IO.FileInfo(FilePath)
 Dim objResponse As System.Web.HttpResponse = System.Web.HttpContext.Current.Response
            objResponse.ClearContent()
            objResponse.ClearHeaders()
            objResponse.AppendHeader("Content-Disposition", "attachment; filename=" & DownloadAs)
            objResponse.AppendHeader("Content-Length", objFile.Length.ToString())
 Dim strContentType As String
 Select Case objFile.Extension
 Case ".txt" : strContentType = "text/plain"
 Case ".htm", ".html" : strContentType = "text/html"
 Case ".rtf" : strContentType = "text/richtext"
 Case ".jpg", ".jpeg" : strContentType = "image/jpeg"
 Case ".gif" : strContentType = "image/gif"
 Case ".bmp" : strContentType = "image/bmp"
 Case ".mpg", ".mpeg" : strContentType = "video/mpeg"
 Case ".avi" : strContentType = "video/avi"
 Case ".pdf" : strContentType = "application/pdf"
 Case ".doc", ".dot" : strContentType = "application/msword"
 Case ".csv", ".xls", ".xlt" : strContentType = "application/vnd.msexcel"
 Case Else : strContentType = "application/octet-stream"
 End Select
            objResponse.ContentType = strContentType
            WriteFile(objFile.FullName)
            objResponse.Flush()
            objResponse.Close()
End Sub
Public Shared Sub WriteFile(ByVal strFileName As String)
 Dim objResponse As System.Web.HttpResponse = System.Web.HttpContext.Current.Response
 Dim objStream As System.IO.Stream = Nothing
 ' Buffer to read 10K bytes in chunk:
 Dim bytBuffer(10000) As Byte
 ' Length of the file:
 Dim intLength As Integer
 ' Total bytes to read:
 Dim lngDataToRead As Long
 Try
 ' Open the file.
                objStream = New System.IO.FileStream(strFileName, System.IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
 ' Total bytes to read:
                lngDataToRead = objStream.Length
                objResponse.ContentType = "application/octet-stream"
 ' Read the bytes.
 While lngDataToRead > 0
 ' Verify that the client is connected.
 If objResponse.IsClientConnected Then
 ' Read the data in buffer
                        intLength = objStream.Read(bytBuffer, 0, 10000)
 ' Write the data to the current output stream.
                        objResponse.OutputStream.Write(bytBuffer, 0, intLength)
 ' Flush the data to the HTML output.
                        objResponse.Flush()
 ReDim bytBuffer(10000) ' Clear the buffer
                        lngDataToRead = lngDataToRead - intLength
 Else
 'prevent infinite loop if user disconnects
                        lngDataToRead = -1
 End If
 End While
 Catch ex As Exception
 ' Trap the error, if any.
                objResponse.Write("Error : " & ex.Message)
 Finally
 If IsNothing(objStream) = False Then
 ' Close the file.
                    objStream.Close()
 End If
 End Try
End Sub

 

NOTE: This code is presented as an example of how you could secure a file.  The above example is intended as a good starting point to implementing your own secure file routine.  Use at your own risk. Hilbert Solutions, LLC is not responsible for any damage this code example might do.  Also note that this examples contains pieces of other examples across the Internet and therefore is not considered to be original in anyway.

Tags:

1 comment(s) so far...

Re: Securing Uploaded Files with ASP.NET

Note: In DotNetNuke you do not need any programming effort - simply use a folder, created to be "secure - FileSystem" for your uploads (grant the appropriate write permission for the designated roles, if you are using DotNetNuke URLControl), and the framework itself will take care to append .resources to the file name - or remove it, when the file is moved to a public folder by the moderator or downloading it using LinkKlick.aspx.

By Sebastian Leupold on  4/22/2009 1:50 AM

Your name:
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
Enter the code shown above in the box below
Add Comment  Cancel 
Search Blog
Blog Archive
Terms Of Use| Privacy Statement Hilbert Solutions, LLC Since 2007