PDA

View Full Version : Help with simple FileSystemObject?


Iconoclast
03-11-2009, 04:11 AM
Hey guys, I've been playing around with ASP more these days and now that I've read about the FileSystemObject I'm trying to play around with it a bit.

What I want to do is to create a really simplistic page with 2 functions:

1) allow the user to create a new directory and name it
2) allow the user to create a new file and name it

I know what the attributes are of the FSO, but what would the code look like?

Also, how would go about outputting a directory file structure? I'm guessing I would need to use a loop and loop through all the folder and filenames?

Any help would be greatly appreciated! Thanks! :D

Old Pedant
03-11-2009, 05:56 AM
WHERE do you want to create the directory???

Inside the website? Or out at some arbitrary place on the server?

Do you have WRITE permissions from the IIS user to wherever you want to do this??? On most shared servers (e.g., GoDaddy and that ilk), you will only have write permissions to directories inside your site that you have explicitly marked as writable.

All that being said...

I'll assume you already have a directory on your website named "data" that is indeed writable. I'll further assume that it is at the root of your site. That is, from a browser you would access a file in the "data" directory via something like:
http://www.yoursite.com/data/somefile.html

Okay, so far?

Now...

We can create a directory inside of "data". Fine.

Now you want to create a file. WHERE is the file supposed to go??? Inside of "data"? Or inside the new directory? Or is the user supposed to choose? Or or or or???

Old Pedant
03-11-2009, 06:03 AM
Here's one directory listing script I had sitting around:

<TABLE border=1 cellpadding=3>
<%
' this needs to be a global:
Dim folderCount
folderCount = 0

Sub OneFolder (fldr, soFar)
Dim subf, fil
folderCount = folderCount + 1
%>
<tr bgcolor="wheat" onClick="flip(<%=folderCount%>);">
<td><%=fldr.Name%></td>
<td><%=fldr.DateCreated%></td>
</tr>
<%

For Each fil In fldr.Files
filPath = soFar & fil.Name
%>
<tr bgcolor="lightyellow" id="SUB_<%=folderCount%>" style="display: none;">
<td><%=fil.Name%></td>
<td><%=fil.DateCreated%></td>
</tr>
<%
Next
For Each subf In fldr.SubFolders
subfPath = soFar & subf.Name & "/"
OneFolder subf, subfPath
Next
End Sub

' start things off:
startAt = Trim(Request("fn")) ' pass in the starting folder in querystring: fn=whatever

Set FSO = Server.CreateObject("Scripting.FileSystemObject")

OneFolder FSO.GetFolder(Server.MapPath("./" & startAt)), startAt
%>
</TABLE>

<SCRIPT language=javascript>
function flip(which)
{
var id = "SUB_" + which;
var rows = document.getElementsByTagName("TR");
for ( row = 0; row < rows.length; ++row )
{
var tr = rows[row];
if ( tr.id == id )
{
tr.style.display = ( tr.style.display == "none" ) ? "block" : "none";
}
}
}
</SCRIPT>

Old Pedant
03-11-2009, 06:04 AM
And here's another one:

<BODY>
<HEAD>
<STYLE>
div.hide { display: none; }
div.show { display: block; }
</STYLE>

<SCRIPT>
function flip( what )
{
var div = document.getElementById(what);
var span = document.getElementById("S"+what);
if ( div.className == "show" )
{
div.className = "hide";
span.innerHTML = "+";
} else {
div.className = "show";
span.innerHTML = "=";
}
return false;
}
</SCRIPT>
</HEAD>
<BODY>
<%
Counter = 0
alertExtensions = ".gif.jpg.bmp."

Sub OneFolder (fldr, soFar, indent)
Dim subf, fil, level, div, ffiles, ffldrs, fcount

Set ffldrs = fldr.SubFolders
For Each subf In ffldrs
subfPath = soFar & subf.Name & "/"
Counter = Counter + 1
div = "DIR" & Counter
%>
<%=indent%><span id="S<%=div%>">+</span>
&nbsp;<A href="#" onClick="return flip('<%=div%>');"><%=subf.Name%></A><br/>
<DIV ID="<%=div%>" class="hide">
<%
OneFolder subf, subfPath, indent & "&nbsp;&nbsp;&nbsp;&nbsp;"
Response.Write "</div><!-- " & level & " -->" & vbNewLine
Next

Set ffiles = fldr.Files
If (ffiles.Count + ffldrs.Count) = 0 Then Response.Write indent & "- [empty]<br/>" & vbNewLine
For Each fil In ffiles
filPath = soFar & fil.Name
filExt = LCase( Mid(fil.Name, InStrRev(fil.Name,".") ) )
alert = ""
If InStr( alertExtensions, filExt & "." ) Then
alert = "&nbsp;<font color=red>IMAGE FILE</font>"
End If
%>
<%=indent%>-&nbsp;<a href="show.asp?fn=<%=escape(filPath)%>">&nbsp;<%=fil.Name%></a><%=alert%><br/>
<%
Next
End Sub

' start things off:
Set FSO = Server.CreateObject("Scripting.FileSystemObject")

OneFolder FSO.GetFolder(Server.MapPath("./")), "./", ""
%>

Old Pedant
03-11-2009, 06:04 AM
And finally a really simple one:

<%
Sub OneFolder( fldr, indent )
Dim subf, fil ' must be local dim!
For Each subf In fldr.SubFolders
Response.Write indent & "+ " & subf.Name & "<br/>" & vbNewLine
OneFolder subf, indent & "&nbsp; &nbsp; "
Next
For Each fil In fldr.Files
Response.Write indent & " -" & fil.Name & "<br/>" & vbNewLine
Next
End Sub

' get things started:
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
OneFolder FSO.GetFolder( Server.MapPath(".") ), ""
%>

Iconoclast
03-11-2009, 04:16 PM
Awesome, thanks for all the code examples, I'm going to spend some time this afternoon and look them over and if I have any further questions I'll post them.

To answer your questions, this is just a little side project of mine to be able to figure out how to do this kind of stuff, so I'm not actually uploading it to a server on the web, I'm just running it right off of my local box (I installed IIS and whatnot in order to do so).

I want the users to be able to create the directory only in the root directory for the website...so if my ASP page is located in my C:\inetpub\wwwroot\index.asp, and they named the directory "test1", it would be created as: C:\inetpub\wwwroot\test1

Similarly, any files they create would be the same...so let's say they create a file called "text1.txt", it would be created as: C:\inetpub\wwwroot\text1.txt

Edit: I also want to mention, I only want to be able to create text files...I know that's all VBScript will allow you to do, and that if I wanted to create .bmps, .gifs, or whatever else it would be more complicated...for the time being I'm only concerned with making .txts

Thanks! :)

Iconoclast
03-11-2009, 04:31 PM
Well I looked over your codes and they're definitely very neat, I wish I understood some of the things you did better than I do.

I liked the first and the last one, although I think I like the last one best as I was confused by what your JavaScript "flip" function in the first example did exactly...but it looked good being output to in a table. Cool stuff.

So now that I have a basic grasp on how to output the folder structure, how would I go about adding functionality to the page to allow a user to create directories and text files within that root folder (as I mentioned in my post above).

Would I need to be using textboxes for them to input the desired names, and then have the onclick event handler of a button call a specific function to be able to create those things? Or am I completely off?

Thanks again for any other help! :D

Old Pedant
03-11-2009, 08:37 PM
Yes to an <INPUT type=text name="NewDirectoryName"> kind of form field.

Yes to an <INPUT type=submit value="Add New Directory">

But no to "event handler" unless you are actually talking about ASP.NET!

And if you are talking about ASP.NET, we should start the conversation all over.

Event handlers in ASP.NET are, generally, "fakes". They actually simply submit the <FORM> to the server and then automatically generated code on the server sends you off to the appropriate server-side code.

With ASP, you have to "roll your own" to do something similar.

I won't go further until you confirm whether we are talking ASP or ASP.NET.

Iconoclast
03-11-2009, 08:45 PM
Yes, sorry, I mean ASP...not ASP.NET.

So, do I need a separate .asp page then to do this? Is that what I set as the "action" for the form?

Iconoclast
03-12-2009, 04:14 PM
Ok, so here's the code that I've got to create a new directory and a new file:

<%
Function CreateDirectory(strDirectory, strPath)
Set objFso = Server.CreateObject("Scripting.FileSystemObject")
strFullName = objFso.BuildPath(strPath, strDirectory)
On Error Resume Next
Err.Clear
Set objFolder = objFso.CreateFolder(strFullName)
CreateDirectory = (Err.Number <> 0)
End Function

Function CreateFile(strFile, strPath)
Set objFso = Server.CreateObject("Scripting.FileSystemObject")
strFullName = objFso.BuildPath(strPath, strFile)
On Error Resume Next
Err.Clear
Set objFile = objFSO.CreateTextFile(strFullName)
objFile.Close
CreateFile = (Err.Number <> 0)
End Function
%>

So the only bit I think I'm still confused about is how to make the page do those functions when the buttons are clicked. I've already got this:

<form name="myForm" action="page2.asp" method="post">

<input type="text" name="newDirectory" />
<input type="submit" value="Create Directory" /><br />
<input type="text" name="newFile" />
<input type="submit" value="Create File" />

</form>

And that's on my page1.asp file...meanwhile, the functions I posted above as well as the code you provided me with are in my page2.asp file. Is this correct?

Old Pedant
03-12-2009, 11:19 PM
Okay, so you ALWAYS want to create the new file inside the new directory, right???

That's what I was asking you before and you kind of dodged the question.

The thing is, if you make two *SEPARATE* submits of the form, one for the directory and one for the file, how will you REMEMBER what directory you just created??? There are several ways to do so, but again, I wonder if you WANT to do that or not? Or do you just want to give both names and do both operations at once???

In other words, you just aren't CLEARLY specifying what actions you want to happen WHEN.

If you always want to specify both the directory and file at the same time, it's dead easy.

<html>
<body>
<%
dirName = Trim(Request("dirName"))
fileName = Trim(Request("fileName"))
Dim fldr
If dirName <> "" AND fileName <> "" Then
' only do anything if BOTH names are given
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
' remember my assumptions:
' we will only work inside of your data directory:
dirPath = Server.MapPath("/data/" & dirName) ' adjust as needed
If FSO.FolderExists( dirPath ) Then
Set fldr = FSO.GetFolder( dirPath )
Response.Write "Folder " & dirPath & " already exists...continuing<br >"
Else
Set fldr = FSO.CreateFolder( dirPath )
Response.Write "Created new Folder " & dirPath & "...continuing<br >"
End If
' so fldr refers to folder, in either case
filePath = fldr.Path & "/" & fileName
If FSO.FileExists(filePath) Then
Response.Write "File " & filePath & " already exists. Done.<p>"
Else
FSO.CreateTextFile filePath
Response.Write "Created file " & filePath & ". Done.<p>"
End If
End If
%>
<form>
Directory name: <input name="dirname">
File name in that directory: <input name="filename">
<input type=submit value="create directory and file">
</form>

Iconoclast
03-12-2009, 11:53 PM
Ok sorry, I guess I didn't catch that question...to answer it, I want any directories being created to be made in the root directory, and same with any files being created...hmmm, didn't I answer that though? Here:

I want the users to be able to create the directory only in the root directory for the website...so if my ASP page is located in my C:\inetpub\wwwroot\index.asp, and they named the directory "test1", it would be created as: C:\inetpub\wwwroot\test1

Similarly, any files they create would be the same...so let's say they create a file called "text1.txt", it would be created as: C:\inetpub\wwwroot\text1.txt (A few posts up)

Would there be a way to have TWO textboxes with ONE submit button? So, let's say that there's a textbox for creating a new directory, and the other for creating a new text file.

Could I use an If statement to check if one of the textboxes was empty, and if so, to proceed to the next one? Or, if both are empty, then have an alert popup and say that no directory or filenames have been specified? Or if both have been filled out it would create both the directory and the text file at the same time? If that's doable, how would that If statement look?

Alternatively, could I put a radio button on the form for the user to select whether they are creating a new directory or text file, and then somehow use that with an If statement to add whichever is selected and get the name from its respective textbox?

Thanks again for all the help mate, I really appreciate it! :D


Edit: For the code you supplied above, the code between the <% %> tags would have to go in my page2.asp, while the form belongs in my page1.asp, correct?

Old Pedant
03-13-2009, 01:04 AM
Okay, I'm going blind as well as senile. Sorry!

So let's rewrite all that. It's actually simpler:

<html>
<body>
<%
dirName = Trim(Request("dirName"))
fileName = Trim(Request("fileName"))
If dirName <> "" OR fileName <> "" Then
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
' directories and files created in root directory:
If dirName <> "" Then
dirPath = Server.MapPath(dirName)
If FSO.FolderExists( dirPath ) Then
Response.Write "Folder " & dirPath & " already exists.<br >"
Else
FSO.CreateFolder dirPath
Response.Write "Created new Folder " & dirPath & "<br >"
End If
End If

If fileName <> "" Then
filePath = Server.MapPath(fileName)
If FSO.FileExists(filePath) Then
Response.Write "File " & filePath & " already exists.<p>"
Else
FSO.CreateTextFile filePath
Response.Write "Created file " & filePath & ".<p>"
End If
End If
Set FSO = Nothing ' not really important, but not a bad idea
End If
%>
<form>
Directory name: <input name="dirname">
File name in that directory: <input name="filename">
<input type=submit value="create directory and file">
</form>

Iconoclast
03-13-2009, 02:25 AM
I get this error when I try to run it:

Microsoft VBScript runtime error '800a0046'

Permission denied

/page2.asp, line 25

This is line 25 of page2.asp:
FSO.CreateFolder dirPath

I thought maybe it was because Firefox didn't have permissions to create in that folder (I'm on Vista, and to even be able to save my files in that location I have to right-click Dreamweaver.exe > Run as Administrator). So I ran Firefox.exe as admin thinking maybe it would solve the problem, but it didn't.

What do I do? :(

Old Pedant
03-13-2009, 05:34 AM
ASP code has *NOTHING* to do with the browser in use.

For that matter ASP code can be invoked WITHOUT ANY BROWSER AT ALL!

I could "hit" an ASP page using a simple command line interface (e.g., a DOS command window or a Linux command line). Or I could use any of several kinds of programs to "hit" the ASP page.

The problem is that your WEB SERVER does not have permissions to write to that directory.

If you go back to my very first post, I warned you about that. I asked you:Do you have WRITE permissions from the IIS user to wherever you want to do this???

Notice that *YOU* being able to write to the directory is *NOT* the same as the web server writing to the directory! The Web Server runs as the "IUSR_xxxx" user, where "xxxx" is the name of the computer running the server. And it is *THAT* user that must have write permissions in the directory where you want to create subdirectories or files.

If you are testing this on your own local machine (using http://localhost) then the easy way for right now is to go grant the EVERYONE user full permissions in that directory.

But for a REAL website, what you are after is horribly dangerous...writing to the main directory. It's why, as I said, most shared hosts will restrict you to writing only to specific directories (or even one specific directory).

Iconoclast
03-13-2009, 07:06 AM
Aha, yes, that fixed it! You're right...I can't thank you enough!

My last question for you: is there a way to automatically append the ".txt" file extension when creating a file?

I only ask because as of now, what happens is it creates the file with the name I specify, but it creates it as filetype "file". Any ideas?

Thanks again! :D

Old Pedant
03-13-2009, 07:34 AM
Just tack it on.

<%
fileName = Trim(Request("filename"))
If fileName <> "" And InStr(filename, ".") = 0 Then fileName = fileName & ".txt"
...
%>

See? If the user gives any file name, at all, and does NOT have a period (implying and extension) in the name, then you just tack on the ".txt".

Iconoclast
03-13-2009, 07:57 AM
Perfect! I can't thank you enough mate, you've been incredibly helpful! +Thanks for you! :D:D