If you need to write an upload script in ASP you typically begin searching
for something that supports binary files and can deal with the data returned by
Request.BinaryRead. There is ADO's stream or you may find some other component,
but all they are limited in some fashion. Storages and files provide the
required functionality, but also give you ability to manage the received data in
much more ways than usual. You can just store it in a file(s) or construct
archive (OLE compound file) and store several uploads in it - deal with them
later may be or use them from the storage directly, feed a memory stream with
the received data and treat it as set of records (like a DB). And, of course,
you can still pass any part of the data to the ASP or ADO methods that require
binary data!
Upload is not the only reason to need access to binary files - you may need
to construct a protected download system and send the files through an ASP page.
Or you may want to construct download packaging system - user selects what
he/she wants to download, your application packs it in one file and user
downloads it and unpacks it locally (could be very simple with ALP on the user's
machine). We will not try to list here all the possible reasons to access binary
files - the benefits are obvious - more features are always a plus. If they are
not required today, further enhancements of the application may need them and if
they are all in one DLL there is no need to spend time to search more and more
components for every particular task.
Have you ever have the synchronization problem with ASP when you need to
read/write to a file from many pages concourently? If so - the solution is
simple. You just create the free threaded version of SFMain (the root component
of the Storages and Files set), then open the desired file and keep it in a
Session or Application variable. Thus all the file operations will occur through
the same instance of the object and will be automatically synchronized avoiding
data loses. If you need better performance do one step further - leave the
files. Load the file into the memory and just update the disk file when the
application unloads for example. You will be still able to use it as text file
or file containing records.
Let see some very simple sample code (more samples are included in the download
package):
Let us send a local file to the client:
Set sf = Server.CreateObject("newObjects.utilctls.SFMain")
Set f = sf.OpenFile(Server.MapPath("somefile.gif"))
Response.ContentType = "image/gif"
Response.BinaryWrite f.ReadBin(f.Size)
Put a file into a storage:
Set sf = Server.CreateObject("newObjects.utilctls.SFMain")
Set stg = sf.OpenStorage(Server.MapPath("mystorage.stg"))
Set f = sf.OpenFile(Server.MapPath("somefile.gif"))
Set strm = stg.CreateStream("somefile.gif")
f.CopyTo strm, f.Size
The same but if we want to copy to directory will look:
Set sf = Server.CreateObject("newObjects.utilctls.SFMain")
Set stg = sf.OpenDirectory(Server.MapPath("mydirectory"))
Set f = sf.OpenFile(Server.MapPath("somefile.gif"))
Set strm = stg.CreateStream("somefile.gif")
f.CopyTo strm, f.Size
Well in fact in case of directory it can be done in much simple way:
Set sf = Server.CreateObject("newObjects.utilctls.SFMain")
sf.CopyFile Server.MapPath("somefile.gif"), Server.MapPath("mydirectory")
But if we want the same code to deal with the both cases it makes sense to
treat the directory as storage.
Let us read some records from a file:
Set sf = Server.CreateObject("newObjects.utilctls.SFMain.free")
Application.Lock
If Not IsObject(Application("TheFile")) Then
Set Application("TheFile") = sf.OpenFile(Server.MapPath("thefile.bin")
End If
Application.Unlock
' To shorten the next statements let use a variable
Set f = Application("TheFile")
Set rec = Server.CreateObject("newObjects.utilctls.SFRecord")
rec.AddField "Name", vbString, 31
rec.AddField "Age", vbLong
rec.AddField "Sex", vbBoolean
rec.AddField "Weight", vbInteger
rec.BindTo f
rec.Filter.unicodeText = False
f.Pos = 0
Application.Lock
While Not f.EOS
Response.Write "Name: " & rec("Name") & " Age: " & reg("Age") & "
"
rec.MoveNext
Wend
Application.Unlock
Looks like a DB, isn't it? But this is just a file. Why using the ASP
Application - this ensures all the operations will be performed with the same
instance of the SFStream object (the f variable in the sample). By default the
files are opened in exclusive mode (can be changed using the optional flags).
Using the same object for each operation will ensure the file consistency if
some other page attempts write operation for example. If the file is personal
for each user session we can use Session instead of Application. Lock method
lacks? Not a problem - create one CustomLock object (in this package too), set
it in a Session variable and use its Lock and Unlock methods to synchronize
the operations.
See the documentation and the samples in the package for more information.