Archive: Find size of file before downloading?


Find size of file before downloading?
I'm using NSISdl to download files remotely, and I would love to know how to find the size of a file out before downloading, so when on the components page I know how big a component is. I wish I could do something like AddSize 5000 or whatever, but I since the installer doesn't download the file until after the components page, I can't check for the file size on the system.

Is there a built in function in NSISdl or another plugin that could allow this? I've looked around the internet functions in the Developer Center and came up empty handed, any help would be greatly appreciated!


i'm using curl to do so, though it's the most elegant solution maybe and it might not work with all servers


http://nsis.sourceforge.net/Inetc_pl...d_DLL_Function


Just to expand a little on what Takhir means - you can use inetc:head to get just the headers off of the server. This -should- contain the size of the file.. but always check..some servers do not provide this information in the headers;
if you've ever tried downloading a file and it can't tell you how far along it is in its download / how much longer it will take, it's because the server did not provide that information.


Hmm... so I'd have to call inetc::head and then parse through the file that it outputs for the Content-Length and then AddSize that? ugh... I haven't done any file parsing in NSIS and wouldn't have the slightest idea where to begin.


it's not so bad, hinmanj - here's a quick example script:


!define DOWNLOAD_URL "http://www.google.com/intl/en_ALL/images/logo.gif"

; inetc.dll in the same folder as the source script.
; can remove this line if you've got it in NSIS\Plugins
!addplugindir "."

OutFile "content-length_test.exe"

Section
inetc::head /TIMEOUT 10000 ${DOWNLOAD_URL} "$EXEDIR\http.headers"
Pop $0
StrCmp $0 "OK" _ok
_error:
MessageBox MB_OK "Could not download."
goto _end
_ok:
StrCpy $R0 -1
FileOpen $0 "$EXEDIR\http.headers" "r"
_nextline:
ClearErrors
FileRead $0 $1
IfErrors _closeFile
StrCpy $2 $1 16
StrCmp $2 "Content-Length: " _found _nextline
_found:
StrCpy $R0 $1 "" 16
goto _closeFile
_closeFile:
FileClose $0
MessageBox MB_OK "File size: $R0 bytes"
_end:
SectionEnd

The above code example worked great for me, but now I realize that it detects the compressed size of my remote zip-files. Could anyone tell me how to detect the unzipped size without downloading the file, or is that not possible?

I turned Animaether's code into a macro, perhaps it could be of use to other beginners like me too:

Usage: !insertmacro SetRemoteFileSize section url-of-remote-file

!macro SetRemoteFileSize sectie bestand
inetc::head /TIMEOUT 10000 ${bestand} "$EXEDIR\http.headers"
Pop $0
StrCmp $0 "OK" _ok${sectie} _error${sectie}
_error${sectie}:
MessageBox MB_OK "Non-fatal error! Could not detect file size of remote media $\"${sectie}$\"."
goto _end${sectie}
_ok${sectie}:
StrCpy $R0 -1
FileOpen $0 "$EXEDIR\http.headers" "r"
_nextline${sectie}:
ClearErrors
FileRead $0 $1
IfErrors _closeFile${sectie}
StrCpy $2 $1 16
StrCmp $2 "Content-Length: " _found${sectie} _nextline${sectie}
_found${sectie}:
StrCpy $R0 $1 "" 16
goto _closeFile${sectie}
_closeFile${sectie}:
FileClose $0
IntOp $R0 $R0 / 1024 ;SectionSize requires kilobytes
SectionSetSize ${${sectie}} $R0
_end${sectie}:
!macroend


You need to provide that information yourself; perhaps include a plain text file with the same name as the compressed file and download that first.

Stu


Alright, that's what I feared. One of the files is hosted on a host of mine, so I could easily put together a little php-script for this purpose. The other one is not, but perhaps I can persuade the maker to provide that information somewhere.

Anyway, thanks for your help!


Unless that information is stored in the header of the Zip file itself you'd need to decompress the Zip file to find out the uncompressed size - maybe a one time PHP script that does it and writes your text file.

Stu


Yes :)

Edit: here's my solution

Create a new php file in the same folder as the file that is to be downloaded:

<?php
$totalsize=0;
$zip = zip_open($saveToDir."something.zip");
while($z = zip_read($zip)) {
$totalfilesize += zip_entry_filesize($z);
}
zip_close($zip);
echo "UnzippedLength: ".$totalfilesize;
?>


Modified code to retrieve the generated string by the php-file:
!addplugindir "."
RequestExecutionLevel user
OutFile "content-length_test.exe"

Section
NSISdl::download_quiet "YOUR URL.php" "$EXEDIR\filesize-za.txt"
Pop $0
StrCmp $0 "success" _ok
MessageBox MB_OK "Could not download."
goto _end
_ok:
StrCpy $R0 -1
FileOpen $0 "$EXEDIR\filesize-za.txt" "r"
_nextline:
ClearErrors
FileRead $0 $1
IfErrors _closeFile
StrCpy $2 $1 16
StrCmp $2 "UnzippedLength: " _found _nextline
_found:
StrCpy $R0 $1 "" 16
goto _closeFile
_closeFile:
FileClose $0
IntOp $R0 $R0 / 1024 ;bytes -> kilobytes
MessageBox MB_OK "retrieved unzipped size: $R0 KB"
Delete "$EXEDIR\filesize-za.txt"
_end:
SectionEnd

Just a thought: You might as well remove the if(zip_entry_filesize($z)==0) continue; line. Quicker to add 0 than to call zip_entry_filesize() twice.

Stu


Good point. I can't seem to edit the code above though