Давайте в этой статье поговорим, как можно скачть файл из сети Интернет с помощью TidHTTP да и еще так, чтобы при этом наша форма не зависала и можно было во время скачивания выполнять какие-то другие функции программы, например набирать текст в TMemo. Для этого как вы помните, а уже и знаете мы будем использовать потоки, да тут TAntiFreeze не обойтись, так как она не сильно нас спасает от зависания, можно сказать делает вид, что нас спасает. Про скачивание файлов из сети Интернет с использованием потоков я говорил в этой статье, а скачивание файлов из сети Интернет с помощью TidHTTP я рассказывал в этой статье. Нам предстоит сделать тоже самое, только с использованием потоков, ничего сложно потоки делать мы уже умеем, скачивать файл из Интернет мы уже умеем, остается самая малость соединить это все дело во единое и чтобы у нас получилась отличная программа. На форме у меня
  • TEdit
  • TidHTTP
  • TButton
  • TprogressBar
Вы спросить зачем TEdit, да затем, чтобы во время скачивания файла можно было понабирать в TEdit какой-нибудь текст и убедиться в том, что форма действительно не зависает.
Давайте для начала создадим наш поток. Для этого я в текущем модуле описал вот такой вот класс
type
 ThreadHTTP=class(TThread)
 private
  Stream:TMemoryStream;
  i:integer;
 public
  procedure Execute;override;
  procedure ShowResult;
end;

Не забываем, что Вы сможете сделать поток с помощью мастера, для этого выполняем команду File-New-Other вкладка New и в данной вкладке выбрать TThread Obejct. Далее в появившемся окне ввести имя потока и нажать на «Ок«. После чего не забудте подключить в Uses данные модули, соответсвенно в модуле потока — модуль главный подключить, а в главной модуле подключить модуль потока. Всмпомним, что процедура Execute - процедура, которая выполняет непосредственно действия потока и синхронизирует другие процедуры, например процедуры результата, в данном случае у нас это процедура ShowResult.

Далее ставим указатель в нашем классе на процедуру Execute и нажимаем комбинацию клавиш — Shift+Crtl+C. Далее я написал код в процедуре Execute и выглядит следующим образом

procedure ThreadHTTP.Execute;
var
 j:integer;
begin
  inherited;
   i:=0;
   j:=0;
   Stream:=TMemoryStream.Create;
   Form1.IdHTTP1.Get('https://zaokomtek.ru/files/VK_APImodul.rar',Stream);
   Form1.ProgressBar1.Max:=Stream.Size;
   while j<=Stream.Size do
    begin
     inc(i);
     Synchronize(ShowResult);
     inc(j);
     Form1.ProgressBar1.Position:=Form1.ProgressBar1.Position+1;
    end;
   Stream.SaveToFile('C:\1.rar');
   Stream.Free;
end;

Как видите я завел переменную i, которая считает сколько мы в текущий момент скачали байт файла, это популярна, чтобы знать как идет скачка.

Процедура ShowResult у меня выглядит следующим образом

procedure ThreadHTTP.ShowResult;
begin
   Form1.Caption:=IntToStr(i)+' kbs';
end;

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

Далее на событие OnClick TButton нам необходимо создать поток и запустить его, чтобы началась скачка, для этого я написал следующее

procedure TForm1.Button1Click(Sender: TObject);
var
 MyHTTP:ThreadHTTP;
begin
   ProgressBar1.Position:=0;
   MyHTTP:=ThreadHTTP.Create(False);
end;

Обнуляем наш TProgressBar и создаем наш поток, и сразу вызываем процедуру Execute.

Как видите ничего сложно нету, чем дальше, тем интереснее. Ну, что ждем следующих статьей по потокам.

Исходники статьи качаем тут

Автор стать - Andrey53

Метки: , , , , , ,




К записи “Скачиваем файл из Интернет с помощью TIdHTTP+потоки” оставлено комментариев: 9.

  1. xdenser:

    Не очень понятен вызов
    inherited;

    в ThreadHTTP.Execute;

    потому что в TThread
    метод Execute
    объявлен вот так
    procedure Execute; virtual; abstract;

    • xdenser:

      такой код будет генерировать исключение
      которое тяжело пропустить
      т.е. он не проверялся перед публикацией

  2. Сергей:

    Кто ж так в потоках лезет в execute к VCL ?
    Form1.ProgressBar1.Position:=Form1.ProgressBar1.Position+1;

  3. alex_ey:

    Уберите этот бред отсюда! Рожденный ползать программировать не сможет… Аффтар не пиши больше такие статьи…

  4. Павел:

    спасибо хорошая статья, много нового узнал

  5. Anton:

    Всем привет, пытаюсь написать инфо грабер для одного сервиса…
    Все отлично, но когда я работаю с сайтом у меня форма зависает, как-то можно это реализовать без потоков??

  6. Andry:

    В потоках нельзя обращаться напрямую к визуальным компонентам!

    Вот так правильно:

    TDownload = class(TThread)
    private
    Stream:TMemoryStream;
    i,Size:integer;
    protected
    procedure Execute; override;
    procedure ShowResult;
    procedure Max;
    end;

    ….

    var
    Form1: TForm1;
    T1:TDownload;

    ….

    implementation

    procedure TDownload.Max;
    begin
    Form1.ProgressBar1.Max:=Size;
    end;

    procedure TDownload.ShowResult;
    begin
    Form1.Caption:=IntToStr(i)+’ kbs’;
    Form1.ProgressBar1.Position:=Form1.ProgressBar1.Position+1;
    end;

    procedure TDownload.Execute;
    var j:integer;
    HTTP:TidHTTP;
    begin
    inherited;
    HTTP:=TIdHTTP.Create(nil);
    i:=0;
    j:=0;
    Stream:=TMemoryStream.Create;
    HTTP.Get(‘https://zaokomtek.ru/files/VK_APImodul.rar’,Stream);
    Size:=Stream.Size;
    Synchronize(Max); //—-!!!!!!
    while j<=Stream.Size do
    begin
    inc(i);
    Synchronize(ShowResult);
    inc(j);
    end;
    Stream.SaveToFile('1.rar');
    Stream.Free;
    HTTP.Free;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    T1:=TDownload.Create(true);
    T1.Priority:=tplower;
    T1.FreeOnTerminate:=true;
    T1.Resume;
    end;

  7. Роман:

    Код бредовый. Кроме вышеуказанных ошибок работы с потоками, тут еще глобальное заблуждение.
    На самом деле этот код сначала читает файл, полностью.
    Потом тупо пытается выводить счетчик на основную форму.
    потом пишет поток в файл.
    То есть паралельности чтения файла и вывода счетчика здесь нет

Оставить комментарий на Павел

Вы можете использовать следующие теги:

*