By Chris Payne
Introduction
NOTE: |
FSO Model Objects |
|
Drive Object |
Provides access to a disk or
network drive |
FileSystemObject Object |
Provides access to a computer’s file
system |
Folder Object |
Provides access to all properties of a
folder |
TextStream Object |
Provides an easy way to access a file’s
contents |
You can use the above objects to do nearly anything on a computer,
including wreak havoc – so be careful how you play with the FSO.
In a web environment, it can be very important to store information,
such as user info, log files, etc. The FSO provides a powerful
and easy way to store your data in an efficient manner. In this
article,
we’ll be mainly concentrating on the FileSystemObject
and TextStream Objects.
NOTE: |
How Do I Use the FSO?
<% Set fso = Server.CreateObject(“Scripting.FileSystemObject”) %>
To be able to use the FSO to perform all your dirty work, you must
first create the object. If you’re familiar with creating objects
in ASP pages, then this next line should be no surprise:
We create the FSO here and set the reference to the variable fso.
We can now use the familiar object.method syntax to perform
file system
manipulations. (Check out the
Visual Basic documentation
to learn more about objects and object
oriented programming.) In this case, we can use fso.method
or fso.
property, as we’ll see in upcoming examples.
NOTE: |
Here is an abridged list of methods available to the
FSO that we will use here to manipulate files:
File Methods |
|
CopyFile |
Copies one or more files from one
place to another |
CreateTextFile |
Creates a file and returns a TextStream
object |
DeleteFile |
Deletes a file |
OpenTextFile |
Opens a file and returns a TextStream object that can be used to read from or append to the file |
For a complete list of all the methods and properties of the FSO,
check out
the Microsoft MSDN reference. Let’s move onto some examples.
Writing Files
<html> <body> <form action=”formhandler.asp” method=”post”> <input type=”text” size=”10″ name=”username”> <input type=”text” size=”10″ name=”homepage”> <input type=”text” size=”10″ name=”Email”> </form> </body> </html>
Suppose you wanted to create a simple guestbook. You could set up a
database and store
users' information there.
However, if you don't
need the power of a database application, you can save yourself some
money and overhead, and use the FSO to store your information. Not to
mention the fact that your ISP may limit your choice of database
options.
Let's assume you'll collect some user information in a form.
Here's the HTML for a simple
form:
Let's look at the script in formhandler.asp that will handle
the form:
<%
' Get form info
strName = Request.Form(“username”)
strHomePage = Request.Form(“homepage”)
strEmail = Request.Form(“Email”)
' create the fso object
Set fso = Server.CreateObject(“Scripting.FileSystemObject”)
So far, this should be nothing new. We take the form variables and
assign them to variables for easier use later on. Now comes the fun
part – writing the file:
path = “c:temptest.txt”
ForReading = 1, ForWriting = 2, ForAppending = 8
' open the file
set file = fso.opentextfile(path, ForAppending, TRUE)
' write the info to the file
file.write(strName) & vbcrlf
file.write(strHomePage) & vbcrlf
file.write(strEmail) & vbcrlf
' close and clean up
file.close
set file = nothing
set fso = nothing
As you recall, the OpenTextFile method returns a TextStream object,
which is another object of the FSO model. The TextStream object
exposes
methods
to manipulate a file's content, such as
Write, ReadLine, and SkipLine. The VB constant vbcrlf generates
a line break.
NOTE: We specify TRUE in the argument list of OpentextFile to |
Now navigate to c:temp and open test.txt. You should see the following
information:
User's name
User's home page
User's email
Of course those words will be replaced by whatever the user entered
in the form. Now anyone can come along and fill out your guestbook
and their information will be stored in this file.
Reading Files
So now we have some nice user information stored in a file, which
happily works as a simple database. Now suppose a user comes along
and wants to view all your wonderful visitors. We've got to
spit that
information out somehow. Since we don't have a database with
nicely structured columns, we'll have to get clever to output
the results we want.
We know that in the file we just created, the first line is the
user's
name, the second line is their homepage, and the third line is their
email address. Every subsequent user who comes along will also have
their information stored in this way, so that every third line will
contain the same type of information. Knowing that, we can now write
some code to grab the info:
<%
' create the fso object
set fso = Server.Createobject(“Scripting.FileSystemObject”)
path = “c:temptest.txt”
' open the file
set file = fso.opentextfile(path, 1) <– For
reading
Now let's grab each line and format it accordingly:
do until file.AtEndOfStream
Response.write(“Name: ” & file.ReadLine & ” “)
Response.write(“Home Page: ” & file.ReadLine & ” “)
Response.write(“Email: ” & file.ReadLine & “<p>”)
loop
' close and clean up
file.close
set file = nothing
set fso = nothing
%>
NOTE: We did a very simple output here, but note that you can |
If you've created and written your file properly, this little loop
will properly list everyone in your database. The ReadLine method reads
one line up to the newline character. Subsequent calls to ReadLine
will read the next lines. AtEndOfStream is a property of the
TextStream
object that lets
us know when we've hit the end of the file.
Suppose for some reason we didn't format the file correctly. If a
user only has 2 lines instead of 3 describing their info, then we
will get some errors here. Our loop gets the next 3 lines
in the file and if there are not 3 more lines to be had, your page
will get mad and throw an error like:
Server object error 'ASP 0177 : 800a003e'
at you. So be sure to add some error
checking to make sure you're not skipping or inserting too many
lines.
Permissions
The internet account (IUSER_MachineName, where MachineName is the name
Now that we've covered the basics, we should discuss permissions.
The FSO runs in the user account that created it. In other words,
if someone accesses your page from the internet, then the internet
account created the FSO. If you are logged onto your computer as
the administrator and you access the page, then the administrator
account created it. This is very
important, because certain accounts have certain permissions, and
the FSO requires a lot of permissions in order to function fully.
of the server) generally has only reading privileges. That means
that users will never be able to write to the guestbook file. There
are,
however, several options to skirt around this issue.
The first, and more difficult, would be to require the user to log
on to the server before they fill out the guestbook. However, the
point of a guestbook is to get information from anonymous users, and
to log users on, we'd have to know who they are, so
we'll skip this option and move on.
The second is to create a directory or file that allows the
IUSER_MachineName
account writing privileges. This can open up some potential
security holes,
because anyone who knows the proper directory and some savvy web skills
can write stuff to your server. This is a big no-no. So you want to
make
sure you place the writeable directory in a nice and hidden spot,
and possibly
place it outside of the web directory structure (i.e. in Windows,
place it in a
directory that is outside the inetpub directory)
Searching with the FSO
You may be thinking “Great, so now I know how to write files. I
could've
figured that out myself.” So you want more tough guy? Let's
try building a
search feature for your web site.
The key to building a search engine is recursion. If you don't
know
what recursion is, find out
why it's cool.
Basically, you write one piece of code that performs a search on
the files in a directory, and then make that same code loop through
all the subdirectories. Since we don't know ahead of time how many
subdirectories there may be, we have to call this piece of code over
and over again until we're through. Recursion in it's
finest.
So let's build the search page. We'll assume that
you've already
built an HTML form for a user to input a search string.
Dim objFolder
Dim strSearchText
Dim objFSO
strSearchText = Request.Form(“SearchText”) <– The
search string' create the FSO and Folder objects
Set fso = Server.CreateObject(“Scripting.FileSystemObject”)
Set objFolder = objFSO.GetFolder(Server.MapPath(“/”))
Search objFolder
The above code simple initializes variables and gets us started.
The meat of the search is performed by the Search function,
described below:
Function Search(objFolder)
Dim objSubFolder
'loop through every file in the current
folderFor Each objFile in objFolder.Files
Set objTextStream = objFSO.OpenTextFile(objFile.Path,1) <– For Reading
'read the file's contents into a
variablestrFileContents = objTextStream.ReadAll
'if the search string is in the file, then
write a link' to the file
If InStr(1, strFileContents, strSearchText, 1) then
Response.Write “<A HREF=””/” & objFile.Name & _
“””>” & objFile.Name & “</A><BR>”
bolFileFound = True
End If
objTextStream.Close
Next
'Here's the recursion part – for each
' subfolder in this directory, run the Search function again
For Each objSubFolder in objFolder.SubFolders
Search objSubFolder
Next
End Function
NOTE: To be able to open files, the FSO requires the actual |
The code above will run through every subdirectory of every folder
under the initial folder that you specified, which in this case,
would be the root web path, specified by “/”. Then we simply open
each file in the directory, see if the desired string is in that file
and display a link to that file if the search string is found. Not
bad, huh?
Note that as the number of files and subdirectories increases,
so will the time it takes to run this search. It's recommended
that
if you need a heavy duty search feature, turn to something else,
such as Microsoft's Index Server.
Content Management with the FSO
<% ' create the fso object set fso = Server.Createobject(“Scripting.FileSystemObject”) path = “c:temptest.txt” strDate = Replace(Date(), “/”, “”) strDir = “c:inetpubwwwrootarticles” & strDate strNewFileName = Hour(Now) & “_” & Minute(Now) & “_” & second(Now) & “.html” ' open the old file set file = fso.opentextfile(path, 1) <– For strText = file.readall set file = nothing ' check for and/or create folder if not fso.folderexists(Server.MapPath(strDir)) then set f = fso.CreateFolder(Server.MapPath(strDir)) else set f = fso.GetFolder(Server.MapPath(strDir)) end if ' create and write new file set file = fso.Createtextfile(f.path & “” & strNewFileName) file.write(strText) set f = nothing file.close set file = nothing ' delete the old file fso.DeleteFile(path & “” & rst(“FileName”) & i) ' clean up set fso = nothing %>
By now, you should have a good taste of the FSO and its methods and
properties. Let's dig a little deeper and do some engineering
design to
tackle a more difficult problem.
Content management is being able to keep track of, manipulate, and
generally perform tasks with content, typically documents in a web
environment. Smart content management does all that in an easy,
painless
fashion. Behind the scenes
of such an application is heavy duty file manipulation. Once again,
enter the FSO. We need to be able to move, delete, rename, and create
files, and our friend the FSO steps in nicely. In the article
above, we
discuss a submission system for writers to
publish their content. What we don't mention is exactly what
to do with
the file once it's up.
First of all, you'll most likely want to rename the file,
since the writer
probably named it something only he would understand or care about.
To be able to keep track of all your documents, you'll want to
rename it
to something unique, that is easily identifiable by your system.
Unfortunately,
the FSO doesn't allow for an easy file renaming, so we'll
have to engineer
a bit.
reading
The lack of the FSO's abilities however can be used to our
advantage here;
we can perform two steps in one. First, we open and read the
file's contents.
I'll assume that we'll want to create a unique folder, as
well as a unique
filename to store the article in. However, since this folder's
path will
change every day, we'll have to first check to see if the folder
already exists, and if it doesn't, create it. This is done by the
if not fso.folderexists
section. We then get that path
and use
it to create the new file (you'll recall that the FSO needs
the full path
name to manipulate files, and the GetFolder
and
CreateFolder
methods return just that – a full path). After we're done with
the new file,
we'll want to get rid of the old one,
so it doesn't clutter up our file system. This is accomplished
with
fso.DeleteFile
.
So the two steps we accomplished here were renaming the file, and
moving
it to a more apropos directory. Note that we could also have done some
more manipulation here, such as editing the text before we wrote it to
the new file.
What You Can't Do
The FSO does have some weaknesses – for instance, it stumbles on
binary files. This includes MS Word documents, many image formats,
and, unfortunately, a lot of other files. You can still, however
otherwise manipulate these files – move them, delete them, etc. What
you can't do is open, read, or write to them. Given some
ingenuity,
a method could be devised to use the FSO to play with binary files,
but many will find it easier to simply use the old Open method.
Another limitation is file size. When you read or write a lot of
content at once, all the information is stored in memory – and the
larger your content, the larger the memory usage. This tends to slow
everything down, so if you need to manipulate really large files,
or a ton of smaller files, consider breaking the files down into
smaller pieces and clearing the memory often (setting your variables
equal to NULL or “”, and releasing your objects ASAP). Moving your
application into a COM object would also tremendously speed up the
process.
You also can't manage permissions and file and folder attributes
with the FSO. A great way to implement security would be to create
the guestbook file we described earlier as read-only, and then change
the attribute to writeable only when we need it, and immediately
change it back. This method is often used in
CGI and
Perl
scripts,
but unfortunately, there's no pleasant way to do this with the
FSO.
What else can I do?
There are a lot of really cool features in the FSO model that most
people
aren't aware of. These are the type of features that you
normally find
out about after you did things the hard way, and you end up
saying “If only I knew that before!”
I'll briefly list the not-so-common but cool functions here.
Little Known FSO Features |
|
GetSpecialFolder Method |
Returns the path to a special Windows folder: the Windows installation folder; the system folder; and the Windows Temporary folder. Syntax: FSO.GetSpecialFolder([0, 1, or 2]) |
GetTempName Method |
Returns a randomly generated temporary file or folder name. Useful when you need to store temporary data (i.e. when you run into the file size limitation described above). |
GetAbsolutePathName Method |
Returns the absolute path of a folder (similar to Server.MapPath). For example, FSO.GetAbsolutePathName(“region”) will return something like “c:mydocsmyfolderregion” |
GetExtensionName Method |
Returns the extension for the last item in a path (i.e. FSO.GetExtensionName(“c:docstest.txt”) will return txt) |
GetBaseName and GetParentFolder Methods |
Returns the base and parent folder name respectively of last item in a path (i.e. FSO.GetParentFolder (“c:docsmydocs”) will return 'docs') |
Drives Property |
Returns a collection of all the drive objects available on the local machine. This is helpful if you ever want to build an explorer type interface. |
You'll want to make sure you build in robust error handling
routines
though, because some of these above functions will return nasty
errors if the specified file or folder does not exist.
Conclusion
Happy scripting!
As we can see, the FSO is very nifty, and we only touched the tip
of the 'berg here. Many of these features
are implemented on big-name sites, and
many of them pay big bucks for applications that can do this
type of thing. Meanwhile the little 'ol FSO sits by and waits
for someone to come across and use his power! Um..whoops, did I
say that aloud?
The takeaway here is that you can build very powerful applications
with
the FSO, as well as accomplish some simples tasks more easily. Keep
this one in your
toolbelt!
About the Author
Chris Payne Currently lives in the Boston area. He has been building
database driven web sites for
several years. In February 2000, he cofounded Enfused Media, Inc, a web
development/gaming firm.
The first development from EMI was www.enfused.com, a massive gaming portal
for gamers as well
as the gaming business. His offline time is spent with his fiance and
their tropical fish.
Email: [email protected]