This screenshot basically shows you how the pictures are grouped using nothing but code. The groupings are all obtained from folder names (Friends), and the picture names (Friends 004..) themselves from the actual files, which leaves me to just copy-paste pictures - that's it!
Introduction
This is my first ever article in CodeProject. I have often felt the need to just place some pictures/files in a folder and let the code do the rest like - maintain the UI, arrange it according to the folders, and restrict access (to an extent that is :-D).
It works like this: you have a folder, say Photos. You may place a number of subfolders, say, Family, Tour to Canada, etc. inside Photos, and the photos are inside these subfolders. Now, (assuming that Photos is in the same folder as the ASP.NET file), this allows you to produce neatly designed groupings (folders) with the files inside it. Let's see how we do it...
Background
Basic knowledge of how the System.IO.Path
and System.IO.Directory
works.. but not necessary. Hey, I built this the first day I learnt ASP.NET, so you do the math.. it takes 10-15 minutes to write the code... and understand it too.
Using the code
First off, we need to build at least one UI element to contain the browsable interface. It could even be the top level document, but I prefer using a Panel
control so that we can design things around it. Now, the Panel
control (let's say Panel1
) will be used dynamically to add label controls that contain the actual UI. (Must seem a little complicated - actually, the resulting HTML has just a <DIV>
tag and <A HREF>
s! That's it!
OK, now comes the code, which is fairly simple:
First off, we include the System.IO
namespace, and that gives us Path
and Directory
to work with. Why? OK.. we need to get the files from the folder first (Directory
allows this), and then use Path
to do some tricks on the filename/folder name.
imports System.IO
The hierarchy of how you store the files (photos, videos etc.) is important: just place folder, say Photos, just where this ASP.NET file goes, and also others, say Videos, Songs etc. Then, you just copy your Photos folders from wherever, and place it inside a subfolder in Photos. Remember, Photos is the top level folder, and say Family is the subfolder. Now this is the name that the program groups the files in Family.
Enough of it... Let's start this thing..
Inside Page_Load
event, first put the folder list inside Photos (as an example) into a new Array
(String Array
). Directory.GetFolders(directory)
allows you to do this.
So:
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
On Error Resume Next
Panel1.Controls.Clear()
Dim directory1$
Dim i%
Dim s() As String
directory1 = Page.MapPath("photos")
s = Directory.GetDirectories(directory1)
For i = 0 To s.Length - 1
s(i) += ".jpg"
createUI(Path.GetFileNameWithoutExtension(s(i)))
Next
End Sub
Now, some stuff that might seem irregular:
directory1 = Page.MapPath("photos")
s = Directory.GetDirectories(directory1)
This code piece gets the folder that the ASP.NET file runs at, and hence you place the Photos folders at the localhost or web server wherever this code is running. s
now contains the folders inside "Photos".
As an aside, I clear the Panel1
controls to be sure and safe that I am not adding controls again and again.
Now to create a browsable interface for each of the folders, we use createUI
routine, which does exactly that: given a folder, it searches for all the files, and writes HTML and <A HREF>
code to support proper interaction.
So, let's face the createUI
(huhuh.. no camel case..:( ) code:
Public Sub createUI(ByVal title$)
On Error Resume Next
Dim i%
Dim d1$, apppath
Dim s() As String
d1 = Page.MapPath("photos\" + title)
s = Directory.GetFiles(d1)
Dim Label1 As New Label
Dim Label2 As New Label
Label1.Text += "<br><center> " & _
"<big> <font style="" georgia "" size=5> <b><center>:: " _
+ title + " ::</b> </font> </big> </center> <br>"
P1.Controls.Add(Label1)
P1.Controls.Add(Label2)
Label2.Text = "<center> <big> "
Dim ext$
For i = 0 To s.Length - 1
ext = Trim(LCase(Path.GetExtension(s(i))))
If ext = ".jpg" OrElse ext = ".jpeg" OrElse _
ext = ".bmp" OrElse ext = ".gif" Then
Label2.Text += "<a href=""photos/" & title & "/"_
+ Path.GetFileName(s(i)) + """>.:: " + _
MakeName(s(i)) + " </a> "
Label2.Text += "<small><small>(" + _
Str(Math.Ceiling(FileLen(s(i)) / 1024)) + _
" KB)</small></small> :: "
End If
Next
Label2.Text += "</big> </center> "
Label1.BorderStyle = BorderStyle.Solid
Label1.BorderWidth = Unit.Pixel(1)
End Sub
A little explanation:
We also MapPath (Page.MapPath)
here, and note that Photos is hard-coded here. But you can pass it as an argument or make it a global variable. It's a simple change.
Two controls, Label1
and Label2
are used to present the HTML (in the form of formatted DIV
tags).
Label1
holds the groupings - like "Family", "Tour to Canada", etc. and Label2
holds the files. It is a formatted DIV
tag with links (A HREF
). We add Label1
and Label2
to the Panel
Controls
list:
Panel1.Add(Control)
..
The main thing I noticed was that, sometimes I may want to restrict access to only some pictures (like once, I had many people accessing 10 MB files simultaneously, and I couldn't even navigate to CodeProject!). You do that by providing more conditions:
ext
holds the extension of the file under consideration. And, here I just check if it's a valid picture file (hence jpg, jpeg, bmp, gif comparisons). Only then do I add the necessary A HREF
tags to point to the respective files. Here I use the Path
namespace to clarify where the file exactly is. Since relative path is very useful (e.g., when you are juggling your files from one server to another), I get rid of the entire folder name (say "http:\\whatever\Photos\Friends\pic.jpg") to just the filename and the subfolder (in this case, "Photos\Friends\pic.jpg").
...Label2.Text+="<a href=""photos/" & _
title & "/" + Path.GetFileName(s(i))...
Then, as an aside, I also write down the file sizes using FileLen()
function.
"<small><small>(" + Str(Math.Ceiling(FileLen(s(i)) / 1024))_
+ " KB)</small></small> :: "
This returns the file size in bytes (Long
), so I divide by 1024 to get it in KB (hope I am not being very very detailed to the point of irritation :-/), converting it to a String
. The rest 2-3 lines of code are for decoration purposes, best left unexplained, and to your disposal to play with :-).
Points of Interest
Tip: sometimes, pictures maybe just 100 bytes (GIF) or so, so I use Math.Ceiling
to display 1 KB instead of the less useful 0 KB :-) Also, I felt the need to hide some files and let the code not display them.
You can try using a method that checks the file attribute for that file, and check if it is hidden, and if so, just continue to the next in For
loop. I am still working on it (Files.GetAttribute
doesn't seem to work). Any ideas are most welcome.
One more thing: in Page_Load
event, I used:
....
s = Directory.GetDirectories(directory1)
For i = 0 To s.Length - 1
s(i) += ".jpg"
createUI(Path.GetFileNameWithoutExtension(s(i)))
Next
....
I add the extension just to fool the GetFileNameWithoutExtension
method, making it think that I want just the filename. Actually, what I need is the innermost folder, which is very difficult to get (using instr
and some odd function .. aargh), hence this little trick.
Another thing that is interesting to try is this: place a thumbnail image on the side of the images, which is fairly straight forward and is explained in nice detail by Karthik. Another utility is to use a helper function (that I made up) to "beautify" the file names (like from "music_by_artist" to "Music By Artist"). I have placed this code in modEssential.vb in the zip.
Alternatives/feedback (on my first ever CodeProject article!) are most welcome.
History
You might want to try out my homip server and check out photos/videos (please don't download anything heavily - already I have terrible problems controlling my friends from accessing it :-D).. I just built this the first day I started working out with IIS/ASP.NET (with my prior knowledge in VB.NET and a few examples in CodeProject), so just let me know mistakes/alternatives/comments.