|
Вопрос # 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);
- end
- end;
 |
Ответ отправил: 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)
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|