| 
| 
 | Вопрос # 158/ вопрос решён / | 
 |  Добрый вечер, уважаемые эксперты! Нужно реализовать обновление программы. Пользуюсь следующей функцией (см. вставку). Первая часть проходит нормально (получение инфы и т.д.), а вот при загрузке файла обновления (~1 MB) данная функция не справляется - скачивает только около 150 KB и говорит, что все скачала. Данный эффект наблюдается при маленькой скорости модема. А надо, чтобы скачивание происходило при любых условиях, пусть даже скорость будет совсем маленькая. И желательно, чтобы прогресс загрузки отображался на ProgressBar. Заранее спасибо... Приложение:Переключить в обычный режим function DownloadFile(SourceFile, DestFile: string): Boolean; begin   try     Result:=UrlDownloadToFile(nil, PChar(SourceFile), PChar(DestFile), 0, nil) = 0;  except     Result:=False;  end;end; 
|  |   Вопрос задал: feenords (статус: 1-ый класс)Вопрос отправлен: 13 ноября 2006, 15:37
 Состояние вопроса: решён, ответов: 4.
 |  Ответ #1. Отвечает эксперт: Alex Van Glukhman Здравствуйте, feenords!Может есть смысл производить обновление - т.е. загрузку файла через TFileStream предварительно сосчитав размер файла и данное значение связав с TProgressBar. Тогда остаётся контролировать полученное количество скачанных байтов, что будет отражено в ProgressBar.
 
|  | Ответ отправил: Alex Van Glukhman (статус: 7-ой класс)Время отправки: 13 ноября 2006, 22:12
 Оценка за ответ: 4
 |  Ответ #2. Отвечает эксперт: Матвеев Игорь Владимирович Здравствуйте, feenords!По-поводу отображения прогресса, UrlDownloadToFile будет вызывать метод IBindStatusCallback.OnProgress интерфейса IBindStatusCallback, если указать его в последнем параметре (смотрите MSDN).
 Есть и другой способ загрузки файлов из интернета. Смотрите в приложении пример, качает с докачкой, использует InternetOpen/InternetReadFile.
 См. прикреплённый файл.
 К ответу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки ответа)
 
 Ответ #3. Отвечает эксперт: min@y™ Писал я когда-то прогу, так, ради развлекухи, для скачивания креативов с удафкома в виде файлов :)). В ней есть и прогрессбар и всё остальное. Могу прислать. 
 В приложении привожу модуль из этой моей проги, который отвечает за закачку файлов.
 Приложение:Переключить в обычный режим unit uDownloader; interface uses  General,//==============================================================================  Classes, SysUtils, WinInet, Windows, ExtCtrls; type  TDownloaderStatusEvent = procedure (Sender: TObject; const ByTimer: Boolean) of object;   TCustomDownloader = class  private    FURL: string;    FBufferSize: Word;    FhInet,    FhFile: HINTERNET;    FStream: TMemoryStream;    FStatus: string;    FFileName: string;    FErrorCode: TDownloaderError;    FDeltaSize: Cardinal;    FTimer: TTimer;    FOnStatus: TDownloaderStatusEvent;    procedure SetURL(const ANewURL: string);    procedure OnTimer(Sender: TObject);    function GetInterval: Cardinal;    procedure SetInterval(const ANewInterval: Cardinal);  protected    procedure DoOnStatus(const ByTimer: Boolean);  public    constructor Create; virtual;    destructor Destroy; override;    procedure Execute; virtual; abstract;     property URL: string read FURL write SetURL;    property BufferSize: Word read FBufferSize write FBufferSize;    property hInet: HINTERNET read FhInet write FhInet;    property Stream: TMemoryStream read FStream;    property Status: string read FStatus;    property FileName: string read FFileName;    property ErrorCode: TDownloaderError read FErrorCode;    property DeltaSize: Cardinal read FDeltaSize;    property Interval:Cardinal read GetInterval write SetInterval;     property OnStatus: TDownloaderStatusEvent read FOnStatus write FOnStatus;  end;   THtmlDownloader = class(TCustomDownloader)  public    procedure Execute; override;  end;   TImageDownloader = class(TCustomDownloader)  private    FFileSize: Cardinal;    FProgress: Integer;  public    constructor Create; override;    procedure Execute; override;    property FileSize: Cardinal read FFileSize;    property Progress: Integer read FProgress;  end; implementation uses Main; { TCustomDownloader } constructor TCustomDownloader.Create;begin  inherited;  FURL:= '';  FBufferSize:= Settings.DownloadBufferSize;  FhFile:= nil;  FhInet:= nil;  FStream:= TMemoryStream.Create;  FStatus:= '';  FErrorCode:= deSuccess;  FDeltaSize:= 0;  FTimer:= TTimer.Create(nil);  FTimer.OnTimer:= OnTimer;  FTimer.Enabled:= False;end; destructor TCustomDownloader.Destroy;begin  FStream.Free;  Ftimer.Free;  inherited;end; procedure TCustomDownloader.DoOnStatus(const ByTimer: Boolean);begin  if Assigned(FOnStatus)    then FOnStatus(Self, ByTimer);end; {function TCustomDownloader.GetFileName: string;var  Index: Integer;begin  Result:= '';   for Index:= Length(FURL) downto 1 do    if FURL[Index] <> '/'      then Result:= FURL[Index] + Result      else Break;end; } function TCustomDownloader.GetInterval: Cardinal;begin  Result:= FTimer.Interval;end; procedure TCustomDownloader.SetInterval(const ANewInterval: Cardinal);begin  if ANewInterval <> FTimer.Interval    then FTimer.Interval:= ANewInterval;end; procedure TCustomDownloader.OnTimer(Sender: TObject);begin  DoOnStatus(True);end; procedure TCustomDownloader.SetURL(const ANewURL: string);begin  if FURL <> ANewURL    then begin           FURL:= ANewURL;           FFileName:= ExtractFileNameFromURL(FURL);         end;end; { THtmlDownloader } procedure THtmlDownloader.Execute;var  Buffer: array of Char;  Success: Boolean;  Readed, ReadedTotal: Cardinal;begin   DoOnStatus(False);  FhFile:= InternetOpenUrl(FhInet,                           PChar(FURL),                           nil,                           0,                           INTERNET_FLAG_NO_COOKIES or INTERNET_FLAG_NO_CACHE_WRITE,                           0);   if FhFile = nil    then begin           FErrorCode:= deInternetProblem;           Exit;         end;   SetLength(Buffer, FBufferSize);    DoOnStatus(False);   ReadedTotal:= 0;  FTimer.Enabled:= True;   repeat    Success:= InternetReadFile(FhFile, @Buffer[0], Length(Buffer), Readed);    if Success      then FStream.Write(Buffer[0], Readed);     Inc(ReadedTotal, Readed);     FDeltaSize:= Readed;    DoOnStatus(False);  until (Readed = 0) or not Success or MainForm.FCancelled;   FTimer.Enabled:= False;   if not Success    then FErrorCode:= deInternetProblem;end; { TImageDownloader } constructor TImageDownloader.Create;begin  inherited;  FFileSize:= 0;  FProgress:= 0;end; procedure TImageDownloader.Execute;var  Buffer: array of Char;  Success: Boolean;  Readed, ReadedTotal: Cardinal;begin   DoOnStatus(False);  FhFile:= InternetOpenUrl(FhInet,                           PChar(FURL),                           nil,                           0,                           INTERNET_FLAG_NO_COOKIES or INTERNET_FLAG_NO_CACHE_WRITE,                           0);     if FhFile = nil    then begin           FErrorCode:= deInternetProblem;           Exit;         end;   if (not InternetQueryDataAvailable(FhFile, FFileSize, 0, 0)) or (FFileSize = 0)    then begin           FErrorCode:= deFileNotFound;           Exit;         end;   SetLength(Buffer, FBufferSize);    DoOnStatus(False);   ReadedTotal:= 0;  FTimer.Enabled:= True;   repeat    Success:= InternetReadFile(FhFile, @Buffer[0], Length(Buffer), Readed);    if Success      then FStream.Write(Buffer[0], Readed);     Inc(ReadedTotal, Readed);     FDeltaSize:= Readed;    FProgress:= Round(100 * ReadedTotal / FFileSize);    if FProgress > 100      then FProgress:= 100;     DoOnStatus(False);    //Sleep(200);  until (Readed = 0) or not Success or MainForm.FCancelled;   FTimer.Enabled:= False;   if not Success    then FErrorCode:= deInternetProblem;end;  end.
|  | Ответ отправил: min@y™ (статус: Доктор наук)Время отправки: 14 ноября 2006, 08:40
 Оценка за ответ: 5
 Комментарий к оценке: Вышлите, если не сложно! (feenords@rambler.ru) |  Ответ #4. Отвечает эксперт: Dron Здравствуйте, feenords!Я, например, использовал такой код - см. приложение. В нём в ProgressBar отображается процесс закачки, а в Label выводится объём уже закачанной части и общий объём файла. Вот эти самые строки (они есть в коде):
 ProgressBar.Position:=FileSize(f_loc)*100 div StrToInt(chType);
 Status.Caption:=Str2+' of '+Str1+' completed';
 Код достаточно надёжный, ни разу меня не подводил.
 Желаю удачи!
 Приложение:Переключить в обычный режим function TfrmVoices.GetInetFile(const fileURL, FileName: String): Boolean; const BufferSize = 1024;var   hSession, hURL: HInternet;   Buffer: array[1..BufferSize] of Byte;  BufferLen: DWORD;  chType    : array[1..20] of Char;  cLength   : cardinal;  cIndex    : cardinal;  f_loc:file;  sAppName: string;  Str1,Str2: String;begin Result:=False; sAppName := ExtractFileName(Application.ExeName); hSession := InternetOpen(PChar(sAppName),INTERNET_OPEN_TYPE_PRECONFIG,nil, nil, 0); try  hURL := InternetOpenURL(hSession,PChar(fileURL),nil,0,0,0);  try   AssignFile(f_loc, FileName);   Rewrite(f_loc,1);   repeat    InternetReadFile(hURL, @Buffer,SizeOf(Buffer), BufferLen);BlockWrite(f_loc, Buffer, BufferLen);    cLength := 250;    cIndex := 0;    HTTPQueryInfo(hURL,HTTP_QUERY_CONTENT_LENGTH,@chType,cLength,cIndex);    Str1:=FloatToStrF(StrToFloat(chType)/(1024*1024),ffNumber,2,2)+' MB';    Str2:=FloatToStrF(FileSize(f_loc)/(1024*1024),ffNumber,2,2)+' MB';    ProgressBar.Position:=FileSize(f_loc)*100 div StrToInt(chType) ;    Status.Caption:=Str2+' of '+Str1+' completed';    Application.ProcessMessages();   until BufferLen = 0;   CloseFile(f_loc);   Result:=True;  finally   InternetCloseHandle(hURL);  end finally  InternetCloseHandle(hSession); endend;
|  | Ответ отправил: Dron (статус: Студент)Время отправки: 14 ноября 2006, 12:09
 Оценка за ответ: 5
 Комментарий к оценке: Спасибо за столь короткую функцию... |  
 Мини-форум вопросаВсего сообщений: 3; последнее сообщение — 15 ноября 2006, 08:53; участников в обсуждении: 2. 
|   | feenords (статус: 1-ый класс), 13 ноября 2006, 22:57 [#1]:Связать закачку с ProgressBar, в принципе, легко... вот ещё бы скачать файл нормально... Подскажите, кто может, какой-нибудь проверенный примерчик. |  
|   | feenords (статус: 1-ый класс), 15 ноября 2006, 08:53 [#3]:Всем спасибо, помогли!.. 2Матвеев Игорь Владимирович
 Комментарий находится у min@y!
 Но все равно спасибо...
 |  31 января 2011, 19:56: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5) Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |