Заметки · 17.11.2023

Скачать файл: Indy или Synapse?

Для скачивания файлов с https потребуются библиотеки libeay32.dll и ssleay32.dll. Развернуть библиотеки из проекта можно с помощью этого модуля.

Ранее я уже приводил пример скачивания файлов без установки дополнительных библиотек, пакетов и модулей. Теперь всё же расскажу и про методы скачивания файлов, используя массивный Indy и более лаконичный Synapse. Все приведённые мной функции являются логическими и возвращают хоть какой-то ответ. В случае, с функцией GetFileIndy — я не стал ставить обработчик ошибки отсутствия библиотек. Предполагается, что за их размещение и наблюдение будет отвечать другой модуль или же функция.

С предисловиями всё. Теперь по теме.

Начну с Indy. Мной использовалась библиотека 10 версии. Не забудьте установить пакет Indy из сетевого диспетчера пакетов и подключить модуль indylaz в блоке uses в файле Вашего проекта (например, project1.lpr).

Indy10 в сетевом диспетчере пакетов IDE Lazarus

Функция скачивания выглядит так:

uses ..., IdHTTP, IdSSLOpenSSL, LazFileUtils,...;

function GetFileIndy(url, filename: string):boolean;
var
  buffer: TFileStream;
  http: TIdHttp;
  ssl: TIdSSLIOHandlerSocketOpenSSL;
begin
  buffer:=TFileStream.Create(filename, fmCreate or fmShareDenyWrite);
  http:=TIdHttp.Create(nil);
  ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  ssl.SSLOptions.Method:=sslvTLSv1_2;
  ssl.SSLOptions.Mode:=sslmUnassigned;
  ssl.SSLOptions.SSLVersions:=[sslvSSLv2,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
  http.IOHandler:=ssl;
  http.HandleRedirects:=true;
  try
    http.Get(url, buffer);
    if FileSizeUtf8(filename)=0
    then
        begin
          DeleteFile(filename);
          result:=False;
        end
    else result:=True;
  except
    result:=False;
  end;
  http.Free;
  ssl.Free;
  buffer.Free;
end;

Методом проб и ошибок я пришёл к такому перечню SSLVersions, который бы позволил и проект собрать, и совместимость с протоколами соблюсти. Разумеется, надо использовать только ту опцию, которая была бы необходима в рамках определённого проекта.

В блоке try я упомянул FileSizeUtf8 (входит в состав модуля LazFileUtils), чтобы проверить полученный файл на пустоту. Здесь логика проста — если размер файла по каким-то причинам равен нулю — затираем его и возвращаем False.

Теперь поговорим о скачивании с Synapse. С ним всё куда проще: не надо указывать версии шифрования и не надо объявлять целую цепочку связок элементов управления.

Кстати, про установку библиотеки Synapse я писал где-то здесь.

Функция скачивания силами Synapse смотрится компактнее и изящнее:

uses ...,  httpsend, ssl_openssl, ...;

function GetFileSynapse(url,filename:string):boolean;
var
  download: THTTPSend;
begin
  download:=THTTPSend.Create;
  try
     download:=THTTPSend.Create;
     if download.HTTPMethod('GET', url)
     then
       begin
         download.Document.SaveToFile(filename);
         download.Free;
         result:=True;
       end
  else result:=False;
  except result:=False;
  end;
end;

Используются обе функции вполне стандартно — достаточно объявить их в нужном участке кода, а раз обе функции логические их можно обернуть в любой удобный обработчик или условие.

Нужно иметь в виду, что функции выполняются в том же потоке, что и всё приложение, поэтому придётся или ждать когда вернётся какой-то результат, или помещать функции в отдельный поток.