Browse Source

Added new DownloadTemporaryFileSize support function to get the size of a file without downloading it. Useful for scripts that want to download multiple files but show a single progress bar.

Martijn Laan 5 years ago
parent
commit
8b7ff7590e
5 changed files with 41 additions and 6 deletions
  1. 10 2
      ISHelp/isxfunc.xml
  2. 23 0
      Projects/Install.pas
  3. 4 3
      Projects/ScriptFunc.pas
  4. 2 0
      Projects/ScriptFunc_R.pas
  5. 2 1
      whatsnew.htm

+ 10 - 2
ISHelp/isxfunc.xml

@@ -1746,7 +1746,7 @@ end;</pre></example>
         <name>DownloadTemporaryFile</name>
         <prototype>function DownloadTemporaryFile(const Url, FileName, RequiredSHA256OfFile: String; const OnDownloadProgress: TOnDownloadProgress): Int64;</prototype>
         <description><p>Downloads the file from the specified URL to a temporary directory using the specified name. To find the location of the temporary directory, use <tt>ExpandConstant('{tmp}')</tt>.</p>
-<p>An exception will be raised if the file wasn't downloaded successfully. Otherwise, returns the number of bytes downloaded.</p>
+<p>An exception will be raised if there was an error. Otherwise, returns the number of bytes downloaded.</p>
 <p>Supports HTTPS (but not expired or self-signed certificates) and HTTP. Redirects are automatically followed and proxy settings are automatically used. Safe to use from services.</p>
 <p>If RequiredSHA256OfFile is not empty it will compare this to the SHA-256 of the downloaded file and raise an exception if the hashes don't match.</p>
 <p>Set OnDownloadProgress to a function to be informed of progress, or <tt>nil</tt> otherwise.</p></description>
@@ -1754,7 +1754,8 @@ end;</pre></example>
 <p><tt>TOnDownloadProgress = function(const Url, FileName: string; const Progress, ProgressMax: Int64): Boolean;</tt></p>
 <p>ProgressMax will be 0 if the file size is still unknown. Return True to allow the download to continue, False otherwise.</p>
 <p>For basic authentication use a special URL format like this: http://username:[email protected]/</p></remarks>
-        <seealso><p><link topic="isxfunc_ExtractTemporaryFile">ExtractTemporaryFile</link></p></seealso>
+        <seealso><p><link topic="isxfunc_DownloadTemporaryFileSize">DownloadTemporaryFileSize</link><br />
+<link topic="isxfunc_ExtractTemporaryFile">ExtractTemporaryFile</link></p></seealso>
         <example><pre>
 [Code]
 function OnDownloadProgress(const Url, Filename: string; const Progress, ProgressMax: Int64): Boolean;
@@ -1779,6 +1780,13 @@ begin
 end;</pre>
 <p>See <i>CodeDownloadFiles.iss</i> for another example.</p></example>
       </function>
+      <function>
+        <name>DownloadTemporaryFileSize</name>
+        <prototype>function DownloadTemporaryFileSize(const Url): Int64;</prototype>
+        <description><p>Returns the size of the file from the specified URL, without downloading the file. If the server does not provide the file size, -1 will be returned.</p>
+<p>An exception will be raised if there was an error.</p>
+<p>See <link topic="isxfunc_DownloadTemporaryFile">DownloadTemporaryFile</link> for other considerations.</p></description>
+      </function>
     </subcategory>
     <subcategory>
       <function>

+ 23 - 0
Projects/Install.pas

@@ -23,6 +23,7 @@ type
 procedure ExtractTemporaryFile(const BaseName: String);
 function ExtractTemporaryFiles(const Pattern: String): Integer;
 function DownloadTemporaryFile(const Url, BaseName, RequiredSHA256OfFile: String; const OnDownloadProgress: TOnDownloadProgress): Int64;
+function DownloadTemporaryFileSize(const Url: String): Int64;
 
 implementation
 
@@ -3574,4 +3575,26 @@ begin
   end;
 end;
 
+function DownloadTemporaryFileSize(const Url: String): Int64;
+var
+  HTTPClient: THTTPClient;
+  HTTPResponse: IHTTPResponse;
+begin
+  if Url = '' then
+    InternalError('DownloadTemporaryFileSize: Invalid Url value');
+
+  LogFmt('Getting size of %s', [Url]);
+
+  HTTPClient := THTTPClient.Create;
+  try
+    HTTPResponse := HTTPClient.Head(Url);
+    if (HTTPResponse.StatusCode < 200) or (HTTPResponse.StatusCode > 299) then
+      raise Exception.CreateFmt('Getting size failed: %d %s', [HTTPResponse.StatusCode, HTTPResponse.StatusText])
+    else
+      Result := HTTPResponse.ContentLength; { Could be -1 }
+  finally
+    HTTPClient.Free;
+  end;
+end;
+
 end.

+ 4 - 3
Projects/ScriptFunc.pas

@@ -121,15 +121,16 @@ const
 
   { Install }
 {$IFNDEF PS_NOINT64}
-  InstallTable: array [0..2] of AnsiString =
+  InstallTable: array [0..3] of AnsiString =
 {$ELSE}
-  InstallTable: array [0..1] of AnsiString =
+  InstallTable: array [0..2] of AnsiString =
 {$ENDIF}
   (
     'procedure ExtractTemporaryFile(const FileName: String);',
     'function ExtractTemporaryFiles(const Pattern: String): Integer;',
 {$IFNDEF PS_NOINT64}
-    'function DownloadTemporaryFile(const Url, FileName, RequiredSHA256OfFile: String; const OnDownloadProgress: TOnDownloadProgress): Int64;'
+    'function DownloadTemporaryFile(const Url, FileName, RequiredSHA256OfFile: String; const OnDownloadProgress: TOnDownloadProgress): Int64;',
+    'function DownloadTemporaryFileSize(const Url: String): Int64;'
 {$ENDIF}
   );
 

+ 2 - 0
Projects/ScriptFunc_R.pas

@@ -761,6 +761,8 @@ begin
     else
       OnDownloadProgress := nil;
     Stack.SetInt64(PStart, DownloadTemporaryFile(Stack.GetString(PStart-1), Stack.GetString(PStart-2), Stack.GetString(PStart-3), OnDownloadProgress));
+  end else if Proc.Name = 'DOWNLOADTEMPORARYFILESIZE' then begin
+    Stack.SetInt64(PStart, DownloadTemporaryFileSize(Stack.GetString(PStart-1)));
 {$ENDIF}
   end else
     Result := False;

+ 2 - 1
whatsnew.htm

@@ -60,7 +60,8 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
     <li>Supports basic authentication.</li>
   </ul>
   </li>
-  <li>Added new <tt>GetSHA256OfFile</tt>, <tt>GetSHA256OfString</tt>, and <tt>GetSHA256OfUnicodeString</tt> support functions.</li>
+  <li>Added new <tt>DownloadTemporaryFileSize</tt> support function to get the size of a file without downloading it.</li>
+  <li>Added new <tt>GetSHA256OfFile</tt>, <tt>GetSHA256OfString</tt>, and <tt>GetSHA256OfUnicodeString</tt> support functions to calculate SHA-256 hashes.</li>
 </ul>
 <p><span class="head2">Inno Setup Preprocessor (ISPP) updates</span></p>
 <p>ISPP now uses 64-bit integers and has new functions to more easily compare version numbers:</p>