Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Obtaining size of generic file/URL object 1

Status
Not open for further replies.

punchme

Programmer
Dec 16, 2003
14
US
In Windows Explorer, when browsing to some location (UNC pathname, drive pathname, FTP URL, HTTP URL, etc.) one can typically right-click on any object displayed and see the Properties. One of these properties is the file size (well, apparently not when browsing via HTTP, but anyway...)

I assume there's some way to script this so I can obtain such file size information programmatically, but browsing through MSDN docs I have not been able to figure it out. Could anyone give me a pointer to the right place to start, or a code sample? Thanks.
 
Take a look at the FileSystemObject aka fso.

Hope This Helps, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884 or FAQ222-2244
 
While the FSO can't access FTP or HTTP sites, the Windows Shell can. Here's a trivial, skeletal sample. I don't have a handy HTTP site that allows folder browsing, but it works on FTP sites.
Code:
Option Explicit

Const BIF_EDITBOX = &H0010
Const BIF_NEWDIALOGSTYLE = &H0040
Const BIF_BROWSEINCLUDEURLS = &H0080
Const BIF_NONEWFOLDERBUTTON = &H0200
Const BIF_SHAREABLE = &H8000
Const ssfDESKTOP = &H0
Const ssfNETWORK = &H12
Const ssfNETHOOD = &H13

Dim objWinSh, lngFlags, objFolder, intX, strList

Set objWinSh = CreateObject("Shell.Application")
lngFlags = BIF_EDITBOX _
        Or BIF_NEWDIALOGSTYLE _
        Or BIF_BROWSEINCLUDEURLS _
        Or BIF_NONEWFOLDERBUTTON _
        Or BIF_SHAREABLE
Set objFolder = _
  objWinSh.BrowseForFolder(0, _
                           "Select a folder by name", _
                           lngFlags, _
                           ssfDESKTOP)
If TypeName(objFolder) <> "Nothing" Then
  If objFolder.Items.Count > 0 Then
    strList = ""
    For intX = 0 To objFolder.Items.Count - 1
      If Not objFolder.Items.Item(intX).IsFolder Then
        strList = strList & CStr(intX) & ": " _
                & objFolder.Items.Item(intX).Name & vbNewLine
      End If
    Next
    intX = InputBox(strList, "Select a file by number")
    If intX <> "" Then
      intX = CInt(intX)
      MsgBox objFolder.Items.Item(intX).Name & " " _
           & objFolder.Items.Item(intX).Size & " bytes"
    End If
    Set objFolder = Nothing
  Else
    MsgBox "No visible files in this folder"
  End If
End If
Set objWinSh = Nothing
 
Thanks! That definitely started me on the right path. I do happen to have a browsable HTTP site under my control, and as it turns out, HTTP doesn't work. My requirements aren't quite as interactive, so here's where I ended up:

Code:
Option Explicit

Dim objWinSh
Dim objFolder
Dim objFolderItem
Dim c

Set objWinSh = CreateObject("Shell.Application")

'Filesystem case
Set objFolder = objWinSh.NameSpace("C:\wget")
Set objFolderItem = objFolder.ParseName("wget.exe")
WScript.Echo("Size is " & objFolderItem.Size)

'FTP case
Set objFolder = objWinSh.NameSpace("ftp://10.12.254.102")
c = objFolder.Items.Count
Set objFolderItem = objFolder.ParseName("3GB.dat")
WScript.Echo("Size is " & objFolderItem.Size)

'HTTP case
Set objFolder = objWinSh.NameSpace("[URL unfurl="true"]http://10.12.254.102/pacific")[/URL]
Set objFolderItem = objFolder.ParseName("http-large.dwg")
WScript.Echo("Size is " & objFolderItem.Size)

A few interesting things:

1) For the FTP case, I found that unless I did something like the "c = objFolder.Items.Count", the FTP connection did not appear to be made (the ParseLine call would not return anything meaningful). Odd, but I have no problem with the workaround.

2) In looking through the Shell stuff, it seems that everything is quite tied to the concept of folders. That is, if I have a complete URL/path such as "ftp://10.12.254.102/3GB.dat", or "C\wget\wget.exe" (which I do in this case), I couldn't figure out a call to which I could just hand over the complete URL/path and get back the object handle to the item directly without going through the intermediate step of accessing the folder separately first. Granted, given the complete URL/path, it's not difficult to separate out the filename portion from the end, process the first part as a folder separately, and then grab the item second. It just seemed odd that there was not an obvious way to combine the two steps into one. If someone has a lead on that, I'd be curious to hear it.

3) As I mentioned, the HTTP case doesn't work. From playing with it, it seems that any nonsense in URL form (e.g. "blah://whatever") returns a TypeName() of "Folder3". So it seems to be seeing my " URL as nonsense, as I get back an object of type "Folder3", but when I try to do something with it (such as parse the name of an item I know is at that browsable web site), I get a Nothing object in return. Ah well. I guess I'll look into scripting IE. I imagine it's possible somewhere in there.
 
Yes, I agree that the Windows Shell scriptable objects leave some things to be desired.

If going after a file, it seems you must first pull out the path and obtain a folder object for that via the Navigate method. Then one can enumerate Items or use the ParseName method on the folder object with the filename part of the full name.

As far as HTTP goes, a few more experiments here suggest that it may only work with WebDAV folders. Just making a web folder browseable isn't enough.

Sorry for the blind alley. I was hoping to offer you a common way to reach out and touch files whether on a local/network filesystem, an FTP server, or an HTTP server.

Scripting IE sucks bigtime in my opinion. It's a lot of extra bloat and clunkiness. I'm not aware of anything else that might have a hope of handling all three connection types for you though.

The other answer may be to use FSO for filesystem files, and something like the INet control for FTP & HTTP.
 
Thanks again for the tip. While looking up information on Internet Transfer Control, I think I found another post of yours that talked about XMLhttp. It turns out this does exactly what I want for the HTTP case, so I have all my bases covered.

Code:
Option Explicit
Dim objXMLhttp

Set objXMLhttp = CreateObject("MSXML2.XMLhttp")
objXMLhttp.open "HEAD", "[URL unfurl="true"]http://buffet.wankcity.org/~rzewski/burger.jpg",[/URL] False
objXMLhttp.send
WScript.Echo(objXMLhttp.GetResponseHeader("Content-Length"))
 
Great!

It doesn't work well for FTP servers, but here's another sample script.
Code:
Option Explicit

Dim objXH

Set objXH = CreateObject("Msxml2.XMLHTTP.3.0")
'False in the next call is the "async" parameter.
'One could pass True and use WSH event handlers,
'or use a Sleep loop until objXH.readyState = 4
'and a counter to "time out" waiting for the
'server response (to avoid hanging forever when
'a server is unresponsive).
objXH.open "HEAD", "[URL unfurl="true"]http://localhost:8111/junk/test.txt",[/URL] _
           False
objXH.send
'See them all:
MsgBox objXH.getAllResponseHeaders
'Fetch the file size:
MsgBox objXH.getResponseHeader("Content-Length")
'Should return nothing, we did HEAD, not GET:
MsgBox CStr(Len(objXH.responseText))

objXH.open "LIST", "ftp://localhost/junk/test.txt", _
           False, "anonymous", "anon@bogus.com"
objXH.send
'Useless for FTP:
MsgBox objXH.getAllResponseHeaders
'Test with a short file, the whole thing
'always seems to be fetched for any FTP URL:
MsgBox CStr(Len(objXH.responseText))
Set objXH = Nothing
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top