Recent

Author Topic: download multiple files  (Read 2444 times)

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
download multiple files
« on: September 25, 2022, 08:17:45 pm »
hello brothers good day, I am using the project of the friend "getmem" of the following link:
https://forum.lazarus.freepascal.org/index.php/topic,52773.0.html
it works perfect, download all files at once, but i have 2 questions:
1. how to detect when each download is finished and show in the virtualtreeview
2. how to download one at a time, then the next one and show it in the virtualtreeview

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes,
  9.   SysUtils,
  10.   Forms,
  11.   Controls,
  12.   Graphics,
  13.   uDownload,
  14.   //opensslsockets,
  15.   Dialogs, StdCtrls,
  16.   VirtualTrees;
  17.  
  18. type
  19.   PData = ^TData;
  20.   TData = record
  21.     FUrl: String;
  22.     FName: String;
  23.     FState: String;
  24.   end;
  25.  
  26.  
  27.   { TForm1 }
  28.  
  29.   TForm1 = class(TForm)
  30.     Button1: TButton;
  31.     VST: TVirtualStringTree;
  32.     procedure Button1Click(Sender: TObject);
  33.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  34.     procedure FormCreate(Sender: TObject);
  35.     procedure VSTGetNodeDataSize(Sender: TBaseVirtualTree;
  36.       var NodeDataSize: Integer);
  37.     procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  38.       Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
  39.   private
  40.     FDownload: TDownload;
  41.     procedure DoOnDownloadProgress(Sender: TObject; {%H-}AFrom, ATo: String; APos, ASize, AElapsed, ARemaining, ASpeed: LongInt);
  42.     procedure DoOnDownloadCompleted(Sender: TObject);
  43.   public
  44.  
  45.   end;
  46.  
  47. var
  48.   Form1: TForm1;
  49.  
  50. implementation
  51.  
  52. {$R *.lfm}
  53.  
  54. { TForm1 }
  55.  
  56. procedure TForm1.FormCreate(Sender: TObject);
  57. var
  58.   Data: Pdata;
  59.   Node: PVirtualNode;
  60. begin
  61.   VST.Clear;
  62.   VST.NodeDataSize := SizeOf(TData);
  63.  
  64.   Node := VST.AddChild(nil);
  65.   Data := VST.GetNodeData(Node);
  66.   Data^.FUrl := 'https://d.winrar.es/d/103z1663045159/zqnGYe1hSuxmWneHCTGQ9Q/winrar-x64-611es.exe';
  67.   Data^.FName := 'winrar.exe';
  68.   Data^.FState := '';
  69.  
  70.   Node := VST.AddChild(nil);
  71.   Data := VST.GetNodeData(Node);
  72.   Data^.FUrl := 'https://download.mozilla.org/?product=firefox-latest&os=win64&lang=es-MX';
  73.   Data^.FName := 'firefox.exe';
  74.   Data^.FState := '';
  75.  
  76.   Node := VST.AddChild(nil);
  77.   Data := VST.GetNodeData(Node);
  78.   Data^.FUrl := 'https://ardownload2.adobe.com/pub/adobe/acrobat/win/AcrobatDC/2200220191/AcroRdrDCx642200220191_MUI.exe';
  79.   Data^.FName := 'adobe_reader.exe';
  80.   Data^.FState := '';
  81.  
  82.   Node := VST.AddChild(nil);
  83.   Data := VST.GetNodeData(Node);
  84.   Data^.FUrl := 'https://mirror.netcologne.de/videolan.org/vlc/3.0.17.4/win64/vlc-3.0.17.4-win64.exe';
  85.   Data^.FName := 'vlc.exe';
  86.   Data^.FState := '';
  87.  
  88.   Node := VST.AddChild(nil);
  89.   Data := VST.GetNodeData(Node);
  90.   Data^.FUrl := 'https://www.avast.com/es-ww/download-thank-you.php?product=FAV-AVAST&locale=es-ww&direct=1';
  91.   Data^.FName := 'avast.exe';
  92.   Data^.FState := '';
  93.  
  94.   Node := VST.AddChild(nil);
  95.   Data := VST.GetNodeData(Node);
  96.   Data^.FUrl := 'https://mirrors.ucr.ac.cr/tdf/libreoffice/stable/7.4.1/win/x86_64/LibreOffice_7.4.1_Win_x64.msi';
  97.   Data^.FName := 'libre_office.msi';
  98.   Data^.FState := '';
  99.  
  100.   Node := VST.AddChild(nil);
  101.   Data := VST.GetNodeData(Node);
  102.   Data^.FUrl := 'https://data-cdn.mbamupdates.com/web/mb4-setup-consumer/offline/mb4-setup-consumer-4.5.14.210-1.0.1751-1.0.59171.exe';
  103.   Data^.FName := 'malwarebytes.exe';
  104.   Data^.FState := '';
  105.  
  106.   FDownload := nil;
  107. end;
  108.  
  109. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  110. begin
  111.     if Assigned(FDownload) then
  112.     FDownload.CancelDownoad;
  113. end;
  114.  
  115. procedure TForm1.Button1Click(Sender: TObject);
  116. var
  117.    node : PVirtualNode ;
  118.    Data: PData;
  119. begin
  120.   // ShowMessage(ExtractFilePath(Application.ExeName));
  121.   node := VST.GetFirst ;
  122.   while assigned (node) do
  123.       begin
  124.       Data := VST.GetNodeData(Node);
  125.  
  126.       {
  127.       ShowMessage(Data^.FUrl);
  128.       ShowMessage(Data^.FName);
  129.       ShowMessage(Data^.FState);
  130.       }
  131.  
  132.       Data^.FState:='downloading';
  133.       FDownload := TDownload.Create;
  134.       FDownload.OnDownloadProgress := @DoOnDownloadProgress;
  135.       FDownload.OnDownloadCompleted := @DoOnDownloadCompleted;
  136.       FDownload.DownloadFile(Data^.FUrl, ExtractFilePath(Application.ExeName)+Data^.FName);
  137.  
  138.  
  139.       node := VST.GetNext(node) ;
  140.       end;
  141.       vst.setfocus;
  142.       vst.Refresh;
  143. end;
  144.  
  145. procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree;
  146.   var NodeDataSize: Integer);
  147. begin
  148.   NodeDataSize := SizeOf(TData);
  149. end;
  150.  
  151. procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  152.   Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
  153. var
  154.   Data: PData;
  155. begin
  156.   // si no existen estos codes, el resultado sera el texto    "NODE"
  157.   Data := VST.GetNodeData(Node);
  158.   case Column of
  159.     0: CellText := Data^.FUrl;
  160.     1: CellText := Data^.FName;
  161.     2: CellText := Data^.FState;
  162.   end;
  163. End;
  164.  
  165. procedure TForm1.DoOnDownloadProgress(Sender: TObject; AFrom, ATo: String;
  166.   APos, ASize, AElapsed, ARemaining, ASpeed: LongInt);
  167. begin
  168.  
  169. end;
  170.  
  171. procedure TForm1.DoOnDownloadCompleted(Sender: TObject);
  172. begin
  173.      ShowMessage('Download completed!');
  174. end;
  175.  
  176. end.

PD: I am using lazarus + virtualtreeview on win10x64
attached project example and image

DLL SSL 32 bit: https://packages.lazarus-ide.org/openssl-1.0.2j-i386-win32.zip
DLL SSL 64 bit: https://packages.lazarus-ide.org/openssl-1.0.2j-x64_86-win64.zip
« Last Edit: September 25, 2022, 08:22:33 pm by Ericktux »

paweld

  • Hero Member
  • *****
  • Posts: 999
Re: download multiple files
« Reply #1 on: September 25, 2022, 09:00:33 pm »
Something like this - in the FDownload class add the OriginalURL property (without fix the protocol), and in OnProgress and OnCopleted we only update the node for the compatible URL
Best regards / Pozdrawiam
paweld

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #2 on: September 25, 2022, 09:30:18 pm »
hello friend thanks for answering, I have tried it and in the first click of the button it downloads only the first one, but if I give it a second click it downloads all

paweld

  • Hero Member
  • *****
  • Posts: 999
Re: download multiple files
« Reply #3 on: September 26, 2022, 12:28:22 am »
Try changing the line
Code: Pascal  [Select][+][-]
  1. Data^.FState := Format('downloading (%f %%)', [APos * 100 / ASize]);
  2.  
to:
Code: Pascal  [Select][+][-]
  1. Data^.FState := Format('downloading (%d bytes)', [APos]);
I didn't add checking if the size is different from 0
Best regards / Pozdrawiam
paweld

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #4 on: September 26, 2022, 01:19:53 am »
hello friend, now it works thanks.  :)
One question, to be able to use the percentage "%" of the download, the variable "ASize" is used, which is the total file size, but it only appears for the first download?
is there a way to get the "ASize" value for all downloads??
Thanks for your time.

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #5 on: September 26, 2022, 06:54:39 am »
I found a solution for now  :), I had to modify the file "udownload.pas" adding the unit "openssl" and below the code "InitSSLInterface;" At the beginning of "procedure TDownload.Execute" I share the project.

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #6 on: February 05, 2024, 03:34:00 pm »
Hello friends, a question, following the same code how can I cancel several downloads  :-\

Zvoni

  • Hero Member
  • *****
  • Posts: 2327
Re: download multiple files
« Reply #7 on: February 05, 2024, 03:52:01 pm »
Hello friends, a question, following the same code how can I cancel several downloads  :-\
You do realize that "TDownload" has a "CancelDownload" Method, as you wrote in your first Post in Line 112, incl. a Typo there?

And FWIW: That code must be leaking.... i see TDownload.Create, but nowhere a FDownload.Free; which, at the latest, i would expect in OnDownloadComplete
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #8 on: February 06, 2024, 02:46:29 pm »
Hello friends, thanks for the advice, here I still have the error, I cannot cancel the selected downloads  :(, I share the project and code with you

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes,
  9.   SysUtils,
  10.   Forms,
  11.   Controls,
  12.   Graphics,
  13.   uDownload,
  14.   //opensslsockets,
  15.   Dialogs,
  16.   StdCtrls, Menus,
  17.   VirtualTrees;
  18.  
  19. type
  20.   PData = ^TData;
  21.  
  22.   TData = record
  23.     FUrl: String;
  24.     FName: String;
  25.     FState: String;
  26.   end;
  27.  
  28.  
  29.   { TForm1 }
  30.  
  31.   TForm1 = class(TForm)
  32.     Button1: TButton;
  33.     MenuItem1: TMenuItem;
  34.     MenuItem2: TMenuItem;
  35.     PopupMenu1: TPopupMenu;
  36.     VST: TVirtualStringTree;
  37.     procedure Button1Click(Sender: TObject);
  38.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  39.     procedure FormCreate(Sender: TObject);
  40.     procedure MenuItem1Click(Sender: TObject);
  41.     procedure PopupMenu1Popup(Sender: TObject);
  42.     procedure VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
  43.     procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
  44.   private
  45.     FDownload: TDownload;
  46.     procedure DoOnDownloadProgress(Sender: TObject; {%H-}AFrom, ATo: String; APos, ASize, AElapsed, ARemaining, ASpeed: Longint);
  47.     procedure DoOnDownloadCompleted(Sender: TObject);
  48.     function GetSelectedNodeData3(var AData: PData): Boolean;
  49.   public
  50.  
  51.   end;
  52.  
  53. var
  54.   Form1: TForm1;
  55.   nro_descargas_total, nro_descarga_actual: integer;
  56.  
  57. implementation
  58.  
  59. {$R *.lfm}
  60.  
  61. { TForm1 }
  62.  
  63. function TForm1.GetSelectedNodeData3(var AData: PData): Boolean;
  64. Var
  65.   Node: PVirtualNode;
  66. begin
  67.   Node := VST.GetFirstSelected;
  68.   while assigned (node) do
  69.         begin
  70.         if Node <> nil then
  71.               begin
  72.                 AData := VST.GetNodeData(Node);
  73.  
  74.                 if TDownload(self).OriginalURL = aData^.FUrl then
  75.                 begin
  76.                 FDownload.CancelDownoad;   // trying to cancel download
  77.                 aData^.FState := 'cancelled';
  78.                 end;
  79.  
  80.                 Result := True;
  81.               end
  82.                   else
  83.                         begin
  84.                           MessageDlg('Please select a node first!', mtInformation, [mbOk], 0);
  85.                           Result := False;
  86.                         end;
  87.         node := VST.GetNextSelected(node) ;
  88.         End;
  89.  
  90.   vst.Refresh;
  91.   vst.Repaint;
  92. End;
  93.  
  94. procedure TForm1.FormCreate(Sender: TObject);
  95. var
  96.   Data: Pdata;
  97.   Node: PVirtualNode;
  98. begin
  99.   {nro_descargas_total:=0;
  100.   nro_descarga_actual:=0;}
  101.  
  102.   VST.Clear;
  103.   VST.NodeDataSize := SizeOf(TData);
  104.  
  105.   Node := VST.AddChild(nil);
  106.   Data := VST.GetNodeData(Node);
  107.   Data^.FUrl := 'https://videolan.ip-connect.info/vlc/3.0.20/win64/vlc-3.0.20-win64.exe';
  108.   Data^.FName := 'vlc.exe';
  109.   Data^.FState := '';
  110.  
  111.   Node := VST.AddChild(nil);
  112.   Data := VST.GetNodeData(Node);
  113.   Data^.FUrl := 'https://files2.codecguide.com/K-Lite_Codec_Pack_1805_Mega.exe';
  114.   Data^.FName := 'klite codec pack.exe';
  115.   Data^.FState := '';
  116.  
  117.   Node := VST.AddChild(nil);
  118.   Data := VST.GetNodeData(Node);
  119.   Data^.FUrl := 'https://raw.githubusercontent.com/ericktux/software_terceros/main/cccp.exe';
  120.   Data^.FName := 'Combined codec pack.exe';
  121.   Data^.FState := '';
  122.  
  123.     Node := VST.AddChild(nil);
  124.   Data := VST.GetNodeData(Node);
  125.   Data^.FUrl := 'https://www.aimp.ru/files/windows/builds/aimp_5.30.2533_w64.exe';
  126.   Data^.FName := 'aimp.exe';
  127.   Data^.FState := '';
  128.  
  129.   Node := VST.AddChild(nil);
  130.   Data := VST.GetNodeData(Node);
  131.   Data^.FUrl := 'https://download.winamp.com/winamp/winamp_latest_full.exe';
  132.   Data^.FName := 'winamp.exe';
  133.   Data^.FState := '';
  134.  
  135.   FDownload := nil;
  136. end;
  137.  
  138. procedure TForm1.MenuItem1Click(Sender: TObject);
  139. Var
  140.   Data: Pdata;
  141.   Node: PVirtualNode;
  142. begin
  143.   GetSelectedNodeData3(Data);
  144. End;
  145.  
  146. procedure TForm1.PopupMenu1Popup(Sender: TObject);
  147. begin
  148.  
  149. End;
  150.  
  151. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  152. begin
  153.   if Assigned(FDownload) then
  154.     FDownload.CancelDownoad;
  155. end;
  156.  
  157. procedure TForm1.Button1Click(Sender: TObject);
  158. var
  159.   node: PVirtualNode;
  160.   Data: PData;
  161. begin
  162.   // ShowMessage(ExtractFilePath(Application.ExeName));
  163.   nro_descargas_total:=0;
  164.   nro_descarga_actual:=0;
  165.  
  166.   node := VST.GetFirst;
  167.   while assigned(node) do
  168.   begin
  169.     if Node <> nil then
  170.       begin
  171.     Data := VST.GetNodeData(Node);
  172.  
  173.       {
  174.       ShowMessage(Data^.FUrl);
  175.       ShowMessage(Data^.FName);
  176.       ShowMessage(Data^.FState);
  177.       }
  178.  
  179.     nro_descargas_total:=nro_descargas_total+1;
  180.     Data^.FState := 'downloading';
  181.     FDownload := TDownload.Create;
  182.     FDownload.OnDownloadProgress := @DoOnDownloadProgress;
  183.     FDownload.OnDownloadCompleted := @DoOnDownloadCompleted;
  184.     FDownload.DownloadFile(Data^.FUrl, ExtractFilePath(Application.ExeName) + Data^.FName);
  185.  
  186.      end;
  187.     node := VST.GetNext(node);
  188.   end;
  189.   vst.SetFocus;
  190.   vst.Refresh;
  191. end;
  192.  
  193. procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
  194. begin
  195.   NodeDataSize := SizeOf(TData);
  196. end;
  197.  
  198. procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
  199. var
  200.   Data: PData;
  201. begin
  202.   // si no existen estos codes, el resultado sera el texto    "NODE"
  203.   Data := VST.GetNodeData(Node);
  204.   case Column of
  205.     0: CellText := Data^.FUrl;
  206.     1: CellText := Data^.FName;
  207.     2: CellText := Data^.FState;
  208.   end;
  209. end;
  210.  
  211. procedure TForm1.DoOnDownloadProgress(Sender: TObject; AFrom, ATo: String; APos, ASize, AElapsed, ARemaining, ASpeed: Longint);
  212. var
  213.   node: PVirtualNode;
  214.   Data: PData;
  215. begin
  216.   node := VST.GetFirst;
  217.   while assigned(node) do
  218.   begin
  219.     Data := VST.GetNodeData(Node);
  220.  
  221.     if TDownload(Sender).OriginalURL = Data^.FUrl then
  222.     begin
  223.  
  224.     {  // trabaja bien
  225.     if ASize > 0 then
  226.     Data^.FState := 'Received: ' + '  ' + FormatSize(APos) + ' / ' + FormatSize(ASize)
  227.     else
  228.     Data^.FState := 'Received: ' + '  ' + FormatSize(APos) + ' / ' + 'Unknown';
  229.     }
  230.  
  231.     if ASize > 0 then
  232.     begin
  233.     Data^.FState :='Downloading '+inttostr(Round((APos/ASize) * 100))+'%';
  234.     //vst.Refresh;
  235.     end;
  236.  
  237.       //Data^.FState := Format('downloading (%f %%)', [APos * 100 / ASize]);  // original
  238.       vst.InvalidateNode(node);
  239.       //vst.Refresh;
  240.       break;
  241.     end
  242.     else
  243.       node := VST.GetNext(node);
  244.   end;
  245. end;
  246.  
  247. procedure TForm1.DoOnDownloadCompleted(Sender: TObject);
  248. var
  249.   node: PVirtualNode;
  250.   Data: PData;
  251. begin
  252.   node := VST.GetFirst;
  253.   while assigned(node) do
  254.   begin
  255.     Data := VST.GetNodeData(Node);
  256.  
  257.     if TDownload(Sender).OriginalURL = Data^.FUrl then
  258.     begin
  259.     nro_descarga_actual:=nro_descarga_actual+1;
  260.       Data^.FState := 'finalized';
  261.       vst.InvalidateNode(node);
  262.       //vst.Refresh;
  263.       break;
  264.     end
  265.     else
  266.       node := VST.GetNext(node);
  267.   end;
  268.   if nro_descarga_actual=nro_descargas_total then ShowMessage('ALL DOWNLOADS COMPLETED');
  269. end;
  270. end.

DLL SSL 64 bit: https://packages.lazarus-ide.org/openssl-1.0.2j-x64_86-win64.zip

Zvoni

  • Hero Member
  • *****
  • Posts: 2327
Re: download multiple files
« Reply #9 on: February 06, 2024, 03:32:52 pm »
Seriously?
Code: Pascal  [Select][+][-]
  1. FDownload.CancelDownoad;   // trying to cancel download

Is your code even entering MenuItem1Click-Routine (and subsequently the GetSelectedNodeData3-Routine)?
« Last Edit: February 06, 2024, 03:36:29 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #10 on: February 06, 2024, 06:02:45 pm »
Yes friend indeed, can you help me??

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: download multiple files
« Reply #11 on: February 06, 2024, 07:29:23 pm »
You have just one FDownload: TDownload
You use that same variable to initiate multiple downloads.
Only the last download is kept in FDownload.

After that you do FDownload.CanelDownoad (which has a type but that isn't the problem).

So only your last download will be cancelled.

If you want the other downloads to cancel you need to save the FDownload instance of all downloads
or save it in the node and use that instance to cancel.


Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #12 on: February 06, 2024, 08:28:12 pm »
I understand friend, I will do some tests and let you know how it goes.

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: download multiple files
« Reply #13 on: February 06, 2024, 08:32:37 pm »
If you didn't find it yet...
You can save the FDownload instance in the Data^ which you connect to the node.
(In line 180/181)
In the right click of the node you can use that instance to cancel.

I didn't look at TDownload itself but if it's not self freeing you also need to free those instances.

Ericktux

  • Sr. Member
  • ****
  • Posts: 345
Re: download multiple files
« Reply #14 on: February 07, 2024, 03:38:41 pm »
Hello friend, good morning, you are right "Download.Cancel Download" only applies to the last download.
Please how can I save an instance of "FDownload" an example  :-\

 

TinyPortal © 2005-2018