- NSIS Discussion
- Find size of file before downloading?
Archive: Find size of file before downloading?
hinmanj
3rd November 2008 04:48 UTC
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!
Yathosho
3rd November 2008 13:44 UTC
i'm using curl to do so, though it's the most elegant solution maybe and it might not work with all servers
Animaether
3rd November 2008 21:13 UTC
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.
hinmanj
4th November 2008 04:49 UTC
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.
Animaether
5th November 2008 19:02 UTC
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
Grytolle
23rd June 2010 13:40 UTC
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
Afrow UK
23rd June 2010 13:43 UTC
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
Grytolle
23rd June 2010 13:52 UTC
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!
Afrow UK
23rd June 2010 13:54 UTC
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
Grytolle
23rd June 2010 14:52 UTC
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
Afrow UK
24th June 2010 10:45 UTC
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
Grytolle
24th June 2010 14:46 UTC
Good point. I can't seem to edit the code above though