Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.02.2009, 12:01   #1
ZeitGeist7
Пользователь
 
Регистрация: 02.02.2009
Сообщений: 54
По умолчанию закачка файла отдельным потоком.

Код:
Function  DownLoad(_LinkLoad, _SaveWay: string) : Boolean ;
  var F: File;
//    ResumePos : DWORD;
    BufferLen,SumSize: DWORD;
    hSession, hURL: HInternet;
    Buffer: array[1..1024] of Byte;
    err: boolean;

begin
try
  SumSize:=0;
//  ResumePos:=0;   //Инициализируемся
  AssignFile (F,_SaveWay);  //Свяжемся с файлом
  ReWrite(f,1);  //А раз нет, так создадим

//Открыли сессию
  hSession:= InternetOpen('X-Kachalka',PRE_CONFIG_INTERNET_ACCESS,nil,nil,0);

//И наш УРЛ
  hURL := InternetOpenURL(hSession,PChar(_LinkLoad),nil,0,0,0);
//          Здесь будет переменная счётчика ^^^^
//Сколько там наш файл весит?
  InternetQueryDataAvailable(hURL, SumSize,0,0);
//label4.Caption:= IntToStr (SumSize); //Сообщим об этом


  REPEAT //Качаем
    err:= InternetReadFile(hURL, @Buffer,SizeOf(Buffer),BufferLen); //Читаем буфер
    IF err= false then //Ошибка чтения
       begin
            Closefile(f);
           Result := false;
          exit;
       end;
     BlockWrite(f, Buffer, BufferLen); //Пишем в файл
     Application.Processmessages;
  UNTIL (BufferLen= 0);
   begin // Or (_DownloadProcessing= FALSE); //Качаем, пока не все или надо
      Result := true;
      Closefile(f);
   end;
except
  Result := false;
end;
end;
вопрос: отдельным потоком как сделать?
эта именно то что мне надо но минус в том кто пока качает вся прога тормозит. выход есть: отдельным потоком запустить но я малость не понял как и что.
мне тут всего-то нужен вызов потока передав ему ссылку и файл и по возможности остановить его выполнение.
спасибо
ZeitGeist7 вне форума Ответить с цитированием
Старый 19.02.2009, 12:18   #2
FANATID
Пользователь
 
Регистрация: 12.02.2009
Сообщений: 62
По умолчанию

после type пишеш

Код:
  MyThread = class(TThread)
  private

  protected
    procedure Execute; override;
  end;
после implementation пишеш

Код:
procedure MyThread.Execute;
begin
 тут код
end;
вот и самый простой поток
FANATID вне форума Ответить с цитированием
Старый 19.02.2009, 13:06   #3
ZeitGeist7
Пользователь
 
Регистрация: 02.02.2009
Сообщений: 54
По умолчанию

а как вызов по кнопке?
и можно "аварийную" остановку реализовать. если вдруг надо прекратить скачивание.
ZeitGeist7 вне форума Ответить с цитированием
Старый 19.02.2009, 13:45   #4
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Цитата:
Сообщение от ZeitGeist7 Посмотреть сообщение
можно "аварийную" остановку реализовать. если вдруг надо прекратить скачивание.
У вас скачивание прекращается по ошибке ERR ? Прекрашается...
Точно так же - вводите свою переменную, например, MYSTOP и проверяете ее значение так же, как проверяете значение ERR. И точно так же выходите из цикла скачивания...
А нужное значение MYSTOP устанавливается вашей кнопкой "аварийной остановки".
mihali4 вне форума Ответить с цитированием
Старый 19.02.2009, 14:32   #5
ZeitGeist7
Пользователь
 
Регистрация: 02.02.2009
Сообщений: 54
По умолчанию

как вызывать то?))) чтобы один и тот же код 15 раз не писать а поступить как с функцией

похоже ответа мне не дождаться....

что-то я не вкуриваю тему... можно более подробный пример работы с потоками?

Последний раз редактировалось KORN; 19.02.2009 в 21:38. Причина: учимся пользоваться правкой
ZeitGeist7 вне форума Ответить с цитированием
Старый 20.02.2009, 08:18   #6
FaTaL
Участник клуба
 
Аватар для FaTaL
 
Регистрация: 09.11.2007
Сообщений: 1,761
По умолчанию

Очень подробно описано в книге М.Фленова "Баблия Delphi" на 565 странице.
FaTaL вне форума Ответить с цитированием
Старый 22.02.2009, 17:35   #7
ZeitGeist7
Пользователь
 
Регистрация: 02.02.2009
Сообщений: 54
По умолчанию

спасибо.
я скачал книгу. прочитал про потоки раз 11.
сделал так как написано в книге:
1) сходил в менюшку, создал tread object. обозвал его TDowloadFile
2) заполнил процедуру procedure TDowloadFile.Execute;своим кодом
3) все переменные кинул сразу после implementation.
4) засунул в uses wininet,

вот только что-то не нашел в книге таких вещей как:
1) передать потоку ссылку откуда качать и путь сохранения файла
2) как добиться чтобы в случае успешного (или нет) завершения поток возвращал true или false.

вот то что я получил(простите что кодом просто не могу файлик отправить - браузер глючит)
Код:
unit DownloadTread;

interface

uses
  Classes {$IFDEF MSWINDOWS} , Windows {$ENDIF} ,wininet;

type
  TDowloadFile = class(TThread)
  private
    procedure SetName;
  protected
    procedure Execute; override;
  end;

implementation

  var F: File;
//    ResumePos : DWORD;
    BufferLen,SumSize: DWORD;
    hSession, hURL: HInternet;
    Buffer: array[1..1024] of Byte;
    err: boolean;

{$IFDEF MSWINDOWS}
type
  TThreadNameInfo = record
    FType: LongWord;     // must be 0x1000
    FName: PChar;        // pointer to name (in user address space)
    FThreadID: LongWord; // thread ID (-1 indicates caller thread)
    FFlags: LongWord;    // reserved for future use, must be zero
  end;
{$ENDIF}

{ TDowloadFile }

procedure TDowloadFile.SetName;
{$IFDEF MSWINDOWS}
var
  ThreadNameInfo: TThreadNameInfo;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
  ThreadNameInfo.FType := $1000;
  ThreadNameInfo.FName := 'TDowloadTreat';
  ThreadNameInfo.FThreadID := $FFFFFFFF;
  ThreadNameInfo.FFlags := 0;

  try
    RaiseException( $406D1388, 0, sizeof(ThreadNameInfo) div sizeof(LongWord), @ThreadNameInfo );
  except
  end;
{$ENDIF}
end;

procedure TDowloadFile.Execute;
begin
try
  SumSize:=0;
//  ResumePos:=0;   //Инициализируемся
  AssignFile (F,_SaveWay);  //Свяжемся с файлом
  ReWrite(f,1);  //А раз нет, так создадим
//Открыли сессию
  hSession:= InternetOpen('X-Kachalka',PRE_CONFIG_INTERNET_ACCESS,nil,nil,0);
//И наш УРЛ
  hURL := InternetOpenURL(hSession,PChar(_LinkLoad),nil,0,0,0);
  InternetQueryDataAvailable(hURL, SumSize,0,0);
  REPEAT //Качаем
    err:= InternetReadFile(hURL, @Buffer,SizeOf(Buffer),BufferLen); //Читаем буфер
    IF err= false then //Ошибка чтения
       begin
            Closefile(f);
           Result := false;
          exit;
       end;
     BlockWrite(f, Buffer, BufferLen); //Пишем в файл
     Application.Processmessages;
  UNTIL (BufferLen= 0);
   begin
      Result := true;
      Closefile(f);
   end;
except
  Result := false;
end;
end;

end.
ZeitGeist7 вне форума Ответить с цитированием
Старый 23.02.2009, 20:45   #8
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

ты не все про потоки прочел!
Цитата:
ВАжно: Методы и свойства обьектов из библиотеки визуальных компонентов могут использоватся только в рамках вызова метода Synchronize, например:
Synchronize(UpdateCaption);

где метод UpdateCaption должен быть подобен такому

procedure MyThread.UpdateCaption;
begin
Form1.Caption:= 'Новый текст метки';
end;
никто тебе не мешает переписать на свой лад
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 25.02.2009, 09:51   #9
ZeitGeist7
Пользователь
 
Регистрация: 02.02.2009
Сообщений: 54
По умолчанию

модуль потока:
Код:
unit DownloadTread;

interface

uses
 Classes , Windows , wininet ;
var
 _ThreadLink, _ThreadFile : string;
 _ThreadResult : boolean;
 _ThreadSize : Integer;
type
 TMyThread = class(TThread)
 private
   { Private declarations }
 protected
   procedure Execute; override;
 end;

implementation
   var
   F: File;
   BufferLen,SumSize: DWORD;
   hSession, hURL: HInternet;
   Buffer: array[1..1024] of Byte;
   err: boolean;
procedure TMyThread.Execute;
begin
FreeOnTerminate := True;
try
 SumSize:=0;                         //_ThreadLink, _ThreadFile
//  ResumePos:=0;   //Инициализируемся
 AssignFile (F,_ThreadFile);  //Свяжемся с файлом
 ReWrite(f,1);  //А раз нет, так создадим
//Открыли сессию
 hSession:= InternetOpen('X-Kachalka',PRE_CONFIG_INTERNET_ACCESS,nil,nil,0);
//И наш УРЛ
 hURL := InternetOpenURL(hSession,PChar(_ThreadLink),nil,0,0,0);
 InternetQueryDataAvailable(hURL, SumSize,0,0);
 REPEAT //Качаем
   err:= InternetReadFile(hURL, @Buffer,SizeOf(Buffer),BufferLen); //Читаем буфер
   IF err= false then //Ошибка чтения
      begin
           Closefile(f);
          _ThreadResult := false;
         exit;
      end;
    BlockWrite(f, Buffer, BufferLen); //Пишем в файл
//     Application.Processmessages;
 UNTIL (BufferLen= 0);
  begin
     _ThreadResult := true;
     Closefile(f);
  end;
except
 _ThreadResult := false;
end;
end;

end.
код вызова потока:
Код:
procedure TRssListForm.DownloadRssBtnClick(Sender: TObject);
var
co: TMyThread;
 Ini: Tinifile;
begin
Ini:=TiniFile.Create(extractfilepath(paramstr(0))+'Options.ini');
co:=TMyThread.Create(true);
_ThreadLink := Ini.ReadString(IntToStr(RssGrid.Row-1),'Link','');
_ThreadFile := Ini.ReadString('MainOption','SaveXmlWayPath',extractfilepath(paramstr(0))+'\') + Ini.ReadString(IntToStr(RssGrid.Row-1),'XmlFileName','');
co.Resume;
co.Priority:=tpLower;
 if not _ThreadResult  then
           LogMemo.Lines.Add(TimeToStr(now)+' id'+IntToStr(RssGrid.Row)+' '+Ini.ReadString(IntToStr(RssGrid.Row-1),'XmlFileName','')+ ' НЕ загружен')
      else LogMemo.Lines.Add(TimeToStr(now)+' id'+IntToStr(RssGrid.Row)+' '+Ini.ReadString(IntToStr(RssGrid.Row-1),'XmlFileName','')+ ' загружен');
co.Terminate;
Ini.Free;
end;

ошибки не выводит. но файлы качает успешно не с первого раза. и даже не со второго.

если циклом
Код:
procedure TRssListForm.DLoadAllBtnClick(Sender: TObject);
var
   Ini: Tinifile;
   _DLoadRss : integer;
   _Link, _File : string;
    co: TMyThread;
begin
 Ini:=TiniFile.Create(extractfilepath(paramstr(0))+'Options.ini');
 LogMemo.Lines.Add(TimeToStr(now)+' принудительное скачивание лент по списку начато.');
for  _DLoadRss := 0 to Ini.ReadInteger('MainOption','NumberOfRss',0) -1 do
begin
  If   Ini.ReadBool(IntToStr(_DLoadRss),'DoDownload',False)  then  // проверка на нужность. указывает пользователь когда не желает чтобы данная ссылка и данный файл был скачан и обработан
      // проверка ссылки на её существование
     begin
         co:=TMyThread.Create(true);
         _ThreadLink := Ini.ReadString(IntToStr(_DLoadRss),'Link','') ;
         _ThreadFile  := Ini.ReadString('MainOption','SaveXmlWayPath',extractfilepath(paramstr(0))+'\')+ Ini.ReadString(IntToStr(_DLoadRss),'XmlFileName','');
         co.Resume;
         co.Priority:=tpLower;
         co.Terminate;
         if not _ThreadResult  then
           LogMemo.Lines.Add(TimeToStr(now)+' id'+IntToStr(_DLoadRss)+' '+Ini.ReadString(IntToStr(_DLoadRss),'XmlFileName','')+ ' НЕ ЗАГРУЖЕН')
      else  if not Ini.ReadBool('MainOption','OnlyErrors',false)  then
           LogMemo.Lines.Add(TimeToStr(now)+' id'+IntToStr(_DLoadRss)+' '+Ini.ReadString(IntToStr(_DLoadRss),'XmlFileName','')+ ' загружен');
      end;
end;

 LogMemo.Lines.Add(TimeToStr(now)+' принудительное скачивание лент по списку закончено.'+#13#10);
 Ini.Free;
end;
то все они неуспешны. файлы либо ноль, либо кусками скачаны
ZeitGeist7 вне форума Ответить с цитированием
Старый 25.02.2009, 16:39   #10
ZeitGeist7
Пользователь
 
Регистрация: 02.02.2009
Сообщений: 54
По умолчанию

слёзно прошу помощи. стебитесь надо мной как хотите и сколько угодно. только помогите довести до ума и функциональности
ZeitGeist7 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Закачка файла с ссылки Titan123 Работа с сетью в Delphi 5 20.10.2008 13:25
Закачка и сохранение файла с удалённого сервера sKarl PHP 2 19.10.2008 11:51
Закачка файла или как не укачатся Dj_smart Софт 8 02.10.2008 09:39
Проблема с потоком Araver Общие вопросы Delphi 4 16.10.2007 04:30