Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.01.09;
Скачать: CL | DM;

Вниз

Как остановить закачку в IdHttp?   Найти похожие ветки 

 
vegarulez   (2010-10-12 10:30) [0]

Привет всем мастерам!
Вопрос состоит в следующем в основном потоке создаётся дополнительный - который скачивает с сервера нужный мне файл, и докачивает его, потом если вдруг соединение к интернету было разорвано. Вопрос заключается в следующем - как принудительно отключить скачивание, по нажатию на кнопоку.
Т.к. там происходит взаиможействи на уровне idhttp в процедуре idHTTP1Work
пытаюсь сделать terminate потока  - но закачка всёравно продолжается. подскажите.


...
const
MY_MESS = WM_USER + 1;
type
 TFormMain = class(TForm)
   ProgressBar1: TProgressBar;
   Edit1: TEdit;
   Edit2: TEdit;
   Button3: TButton;
   Button8: TButton;
...

 type
 TDownLoadfile = class(TThread)
 private
   FSourceFile, FSourceURL: string;
   FSizeFile: Dword;
   IdHTTP1:TidHttp;
   protected
     procedure Execute;override;
   public
     property SourceURL:string read FSourceURL write FSourceURL;
     property SourceFile:string read FSourceFile write FSourceFile;
     property SizeFile:Dword read FSizeFile write FSizeFile;
     procedure idHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer);
     procedure idHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer);
    procedure idHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
 end;

...

procedure TFormMain.Button3Click(Sender: TObject);
begin
 SaveDialog1.FileName:=copy(Edit1.Text,LastDelimiter("\/",Edit1.Text)+1,maxint);
 if SaveDialog1.Execute then
    Edit2.Text:=SaveDialog1.FileName;
end;

procedure TFormMain.MyProgress(var msg: TMessage);
begin
 case msg.WParam of
 0:
  begin
   {label4.Caption:= formatfloat("0.00",msg.LParam / 1024 / 1024) +" мб ("+inttostr(msg.LParam)+")";
   L_P_Num_1.Caption:= formatfloat("0.00",(RestartPos+msg.LParam)  / 1024 / 1024) +" мб ("+inttostr(RestartPos+msg.LParam) +")";}

   ProgressBar1.Max:=RestartPos+msg.LParam;
   ProgressBar1.Position:=0;
  end;
 1:
  begin
   {label5.Caption:=formatfloat("0.00",msg.LParam / 1024 / 1024)+" мб ("+inttostr(msg.LParam)+")";
   label10.Caption:= formatfloat("0.00",(RestartPos+msg.LParam) / 1024 / 1024) +" мб ("+inttostr(RestartPos+msg.LParam)+")"+" [ "+formatfloat("0",((RestartPos+msg.LParam)/ProgressBar1.Max*100)) +"% ]";}

   ProgressBar1.Position:=RestartPos+msg.LParam;
  end;
 end;
end;

procedure TFormMain.thrTerminate(Sender: TObject);
begin
 ShowMessage("Готово");
 Button8.Enabled:=true;
end;

procedure TDownLoadfile.idHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
 AWorkCount: Integer);
begin
 PostMessage(Application.MainForm.Handle,MY_MESS,1,AWorkCount);
end;

procedure TDownLoadfile.idHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
 AWorkCountMax: Integer);
begin
 PostMessage(Application.MainForm.Handle,MY_MESS,0,AWorkCountMax);
end;

procedure TDownLoadfile.idHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
//
end;

procedure TFormMain.BT_Stop_downloadClick(Sender: TObject);
var
t:TDownLoadfile;
begin
t.IdHTTP1.EndWork;

end;

{ TDownLoadfile }

procedure TDownLoadfile.Execute;
var

FileDate: TDateTime;
FileType: string;
SourceFileSize: Dword; // размер исходного файла который собираемся скачивать
fDownloadStream: TFileStream;
begin
IdHTTP1:=TIdHTTP.Create(nil);
IdHTTP1.OnWork:=IdHTTP1Work;
IdHTTP1.OnWorkBegin:=IdHTTP1WorkBegin;
IdHTTP1.OnWorkEnd:=IdHTTP1WorkEnd;
IdHTTP1.ProtocolVersion := pv1_1; //pv1_1
IdHTTP1.HandleRedirects := True;
IdHTTP1.Head(SourceURL);
SourceFile :=IdHTTP1.Response.RawHeaders.Text; // Values["ETag"], """, "", [rfReplaceAll]), "-", "", [rfReplaceAll]);  //
SourceFile := StringReplace(StringReplace(IdHTTP1.Response.RawHeaders.Values["ETag"], """, "", [rfReplaceAll]), "-", "", [rfReplaceAll]);  //   Text;
SourceFile := IdHTTP1.URL.Document;
SourceFileSize := IdHTTP1.Response.ContentLength;

if SourceFileSize>SizeFile then           // значит файл не докачан или его нет вовсе.
Begin
FileDate := IdHTTP1.Response.LastModified;
FileType := IdHTTP1.Response.ContentType;

if FileExists(IdHTTP1.URL.Document) then
 begin
  fDownloadStream := TFileStream.Create(SourceFile, fmOpenReadWrite);
  fDownloadStream.Position:=SizeFile;
  Idhttp1.Request.Range:=Format("%d-%d",[fDownloadStream.Position,SourceFileSize]);
  fDownloadStream.Seek(fDownloadStream.Position,soFromBeginning);
 end
else
 begin
  fDownloadStream := TFileStream.Create(SourceFile, fmCreate);
  fDownloadStream.Seek(0,soFromBeginning); //
 end;
IdHTTP1.Request.ContentType := FileType;
IdHTTP1.Request.ContentRangeStart := fDownloadStream.Position;
IdHTTP1.Request.ContentRangeEnd := SourceFileSize;
try
 IdHTTP1.Get(SourceURL,fDownloadStream);
finally
 fDownloadStream.Free;
 IdHTTP1.Free;
end;
End
else
terminate;
end;

function GetFileSize(FileName: String): Integer;
var
 FS: TFileStream;
begin
 try
   FS := TFileStream.Create(Filename, fmOpenRead);
 except
   Result := -1;
 end;
 if Result <> -1 then Result := FS.Size;
 FS.Free;
end;

procedure TFormMain.Button8Click(Sender: TObject);
var
t:TDownLoadfile;
begin

 Button8.Enabled:=false;

 //Создадим класс потока.
 //Поток для начала будет остановлен
 t:=TDownLoadfile.Create(true);
 //Передадим параметры потоку
 t.SourceURL:=Edit1.Text;
 t.SourceFile:=Edit2.Text;
 RestartPos:=0;
 //Если на винте есть файл то считаем, что нужно докачивать
 if FileExists(Edit2.Text) then
  RestartPos:=GetFileSize(Edit2.Text);    //*128
 t.SizeFile:=RestartPos;

 //Поток должен удалить себя по завершению своей работы
 t.FreeOnTerminate:=true;
 t.OnTerminate:=thrTerminate;

 //И запустим его на закачку.
 t.Resume;
 //Теперь с процедуры мы выйдем, но поток работает
 //и живёт своей жизней
end;


 
Сергей М. ©   (2010-10-12 11:06) [1]

Из другого потока вызови IdHTTP.Socket.Close, тогда IdHTTP.Get() возвратит управление с соотв.исключением


 
vegarulez   (2010-10-12 11:16) [2]

перенёс описание idhttp1 в type

 type
 TDownLoadfile = class(TThread)
 private
   FSourceFile, FSourceURL: string;
   FSizeFile: Dword;
  IdHTTP1:TidHttp;

   protected
     procedure Execute;override;
   public
     property SourceURL:string read FSourceURL write FSourceURL;
     property SourceFile:string read FSourceFile write FSourceFile;
     property SizeFile:Dword read FSizeFile write FSizeFile;
     procedure idHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer);
     procedure idHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer);
    procedure idHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
 end;


и пытаюсь
его остановить как ты посоветовал

procedure TFormMain.BT_Stop_downloadClick(Sender: TObject);
var
t:TDownLoadfile;
begin
t.IdHTTP1.Socket.Close;

end;


вывваливается ошибка (


 
DiamondShark ©   (2010-10-12 12:10) [3]


> вывваливается ошибка (

Где? Если здесь:
IdHTTP1.Get(SourceURL,fDownloadStream);
то так и должно быть.


 
Сергей М. ©   (2010-10-12 12:46) [4]


> перенёс описание idhttp1 в type
>


Нафига ?

Достаточно у TDownLoadfile объявить публ.метод а-ля AbortConnection, в теле которого вызывать IdHTTP.Socket.Close


 
vegarulez   (2010-10-13 10:14) [5]

Вроде всё сделал как ты посоветовал.
Но ничего не получается... ((

Посмотри плиз, если не сложно - я отправил тестовый примерчик с которым работаю на
http://zalil.ru/29807305
весит 10 кб

У меня вываливается ошибка - Access violation at address ... in module...


 
sniknik ©   (2010-10-13 10:28) [6]

> Access violation at address ... in module...

procedure TFormMain.BT_Stop_downloadClick(Sender: TObject);
var
t:TDownLoadfile;
begin
t.IdHTTP1.Socket.Close;

end;


объект t не инициализирован/не существует.


 
Сергей М. ©   (2010-10-13 11:04) [7]

procedure TForm1.Button3Click(Sender: TObject);
var
t:TDownLoadfile;
begin
t.AbortConnection;
end;

в t мусор


 
vegarulez   (2010-10-13 11:10) [8]

я же определяю переменную t как TDownLoadfile, иначе как мне из основного потока обращаться к элементам дочернего потока.

из примера который скинул на залил.ру:
procedure TDownLoadfile.AbortConnection();
begin
idhttp1.Socket.Close;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
t:TDownLoadfile;
begin
t.AbortConnection;
end;


 
vegarulez   (2010-10-13 11:11) [9]

Сергей М. ©   (13.10.10 11:04) [7]

а как тогда правильно реализовать???


 
Сергей М. ©   (2010-10-13 11:23) [10]

1. Сделать t полем класса формы, а не лок.переменной

2. В обработчике OnTerminate нилить t:

procedure TForm1.thrTerminate(Sender: TObject);
begin
 t := nil;
 ShowMessage("Готово");
 Button4.Enabled:=true;
end;

3.
procedure TForm1.Button3Click(Sender: TObject);
begin
if Assigned(t) then
 t.AbortConnection;
end;


 
vegarulez   (2010-10-13 16:35) [11]

давай по пунктам

что значит сделать полем класса формы?
т.е. объявить в type относящемуся к форме, т.е. к unit1 в public секции
t:Form1 ?

если сделать так, то процедура AbortConnection должна быть объявлена тоже в type относящемуся к unit1, чтобы компилятор её увидел и не сругнулся, соответсвенно если в этой процедуре будет обращаение к idhttp1 объявленному в type относящемуся к TDownLoadfile - то он его не видит и ругается...  (

прошу не кидать в меня кирпичом - но реально ничего не понял (((


 
vegarulez   (2010-10-13 16:38) [12]

если же t объявлять в type относящемуся к unit1
t:TDownLoadfile
то он пока ещё не видит объявления TDownLoadfile которое будет ниже и тоже ругается на переменную t...

p.s. про кирпичи - тоже что в предыдущем посте...


 
Сергей М. ©   (2010-10-13 16:55) [13]

TForm1 = class(TForm)
..
private
 t:TDownLoadfile;
..
end;

....

t := TDownLoadfile.Create(...);


 
Palladin ©   (2010-10-13 20:35) [14]

по-моему на этом сайте не хватает еще одной конференции


 
Сергей М. ©   (2010-10-13 21:24) [15]


> Palladin ©   (13.10.10 20:35) [14]


"Патрепацца" ?)


 
Palladin ©   (2010-10-13 21:25) [16]

не )
Основная ("Начинающим" ("Никогда не закончащим"))


 
Сергей М. ©   (2010-10-13 22:02) [17]


> Palladin ©   (13.10.10 21:25) [16]


Я понял про что ты)

Но лучше бы таки "Орешник" реанимировать)


 
sniknik ©   (2010-10-15 18:27) [18]

> не )
> Основная ("Начинающим" ("Никогда не закончащим"))
детский сад. с лозунгом "нас не научишь..." под песню та-ту.


 
vegarulez   (2010-10-17 14:38) [19]

Сергей М. ©   (13.10.10 16:55) [13]

Я же написал vegarulez   (13.10.10 16:38) [12]
что когда так делаю - выскакивает ошибка при компиляции.
Так как

 type
 TDownLoadfile = class(TThread)
 private
...
 end;


Описан после описния TForm1 = class(TForm)
то он ругается при компиляции на

TForm1 = class(TForm)
..
private
t:TDownLoadfile;
..
end;


т.к. не знает что такое TDownLoadfile


 
Anatoly Podgoretsky ©   (2010-10-17 15:13) [20]

> vegarulez  (17.10.2010 14:38:19)  [19]

Поставь перед  TDownLoadfile = class;


 
sniknik ©   (2010-10-17 15:42) [21]

имхо, лучше описать сам поток до формы... (какие то проблемы с тем что что форма не первая?), а еще лучше в отдельном модуле и прописать его в юзес раздела интерфасе.


 
Плохиш ©   (2010-10-17 16:14) [22]


> vegarulez   (17.10.10 14:38) [19]

Тебе уже предлагали нанять программиста?


 
Palladin ©   (2010-10-17 16:47) [23]

Предлагаю нанять программиста.


 
Anatoly Podgoretsky ©   (2010-10-17 17:28) [24]

Все решение перебраны и это тоже.


 
vegarulez   (2010-10-17 17:41) [25]

Anatoly Podgoretsky ©   (17.10.10 15:13) [20]
sniknik ©   (17.10.10 15:42) [21]

Спасибо большое.


 
Anatoly Podgoretsky ©   (2010-10-17 17:52) [26]

> vegarulez  (17.10.2010 17:41:25)  [25]

Да не за что, мы приложили все силы.


 
HF-Trade ©   (2010-10-19 07:27) [27]


> Из другого потока вызови IdHTTP.Socket.Close, тогда IdHTTP.
> Get() возвратит управление с соотв.исключением

Почему из другого потока?
Поясните почему не будет работать -
...
{В потоке}
 AIdHttp := TIdHttp.Create(nil);
 AIdHttp.OnWork := Form1.IdHttp1Work;
Try
 Try
  AIdHttp.Get(URL);
 Except
 end;
Finally  
 AIdHttp.Free;
....
{На форме}
procedure TForm1.IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
IF Start = False Then
 (ASender as TIdHttp).Socket.Close;
end;


 
HF-Trade ©   (2010-10-19 07:39) [28]

ошибся, Work, конечно, не workend


 
sniknik ©   (2010-10-19 08:10) [29]

> Почему из другого потока?
а почему у тебя так же? вот Http.Get у тебя в дополнительном, а Start для остановки ты False  будешь присваивать в каком? судя по всему в другом, основном.
хочешь попытайся в том же, дополнительном, посмотрим как у тебя получится.


 
HF-Trade ©   (2010-10-19 08:37) [30]

ммм... событие Work можно описать и в доп.потоке.
Я и спрашиваю -
1. Почему из другого потока?
2. Почему не работает код выше? хотя там из VCL закрываем сокет, он тупо висит пока не закончится ConnectionTimeout


 
HF-Trade ©   (2010-10-19 08:43) [31]

То что Start присвоить false из другого потока понятно(основного к примеру), ибо доп.поток висит на Get, но сама процедура Work(если она созданна в доп. потоке), должна работать и в нем?


 
sniknik ©   (2010-10-19 09:32) [32]

> но сама процедура Work(если она созданна в доп. потоке), должна работать и в нем?
с чего такие инсинуации? код работает там где вызван, а не там где описан.

> Я и спрашиваю -
ты навыдумывал себе "страшилок" и спрашиваешь не по тому что предлагали, а по тому, что у тебя в голове.


 
sniknik ©   (2010-10-19 09:38) [33]

> Почему не работает код выше?
а он действительно не работает? тогда причина однозначна - вызов Get синхронный, пока не выполнится, дрогой код в этом потоке (неважно где описан) выполнятся не будет.

(вариант когда будет, это если описан метод типа onWorkInProccess который периодически вызывается в самом Get)



Страницы: 1 вся ветка

Текущий архив: 2011.01.09;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.006 c
3-1250675499
salexn
2009-08-19 13:51
2011.01.09
DCOMConnection и проверка его существования


2-1287398190
AnGel
2010-10-18 14:36
2011.01.09
Пеоедача данных через локальную сеть


2-1286986134
infectioni
2010-10-13 20:08
2011.01.09
параметры куба


2-1286865219
Den
2010-10-12 10:33
2011.01.09
Как проверить есть ли данные в поле


2-1287088978
Archvile
2010-10-15 00:42
2011.01.09
Непонятки с выводом записи