Ściąganie plików - dokończenie transferu
dziadek Prokop
W związku z tym że zauważyłem iż często padają pytania o dokończenie
transferu ściąganego pliku - a jestem w temacie ;)
Złożyłem do kupki te fragmenty kodów które można znależć w necie
i podaje poniżej kodzik który można bardziej rozbudować o ile znajdzie się
chętny.
Nie rozpisuje się na temat jego działania ponieważ staram się przy
instrukcjach opisywać ich znaczenia.
A to nawet dlatego że jestem starym sklerotykiem i po tygodniu nie pamiętam
co z czym sie je i jak używa :)
//dziadek Prokop ;)
UNIT Unit1;
interface
uses
Wininet,
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
btnSciagnij: TButton;
btnZatrzymaj: TButton;
ProgressBar1: TProgressBar;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
Edit2: TEdit;
PROCEDURE btnSciagnijClick(Sender: TObject);
PROCEDURE btnZatrzymajClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
VAR
Form1 :TForm1;
Stop :Boolean;
{***************************************************}
IMPLEMENTATION {$R *.dfm}
//Procedura ściąga lub "dociąga" plik z internetu...
PROCEDURE TForm1.btnSciagnijClick(Sender: TObject);
var
adresURL,nazwaPliku :String;
plik :File;
inOpen,inURL :HINTERNET;
rozmiar,ileZnakow,rozmiarPliku :DWORD;
dwBufLen, dwIndex, sciagnieto :DWord;
bufor :array[1..1024] of byte;
buf :Pointer;
Begin
//ustawiamy dane...
inOpen:= nil; inURL:= nil;
rozmiarPliku:= 0;
rozmiar:= 0;
ProgressBar1.Position:= 0;
//zmienna z adresem URL z którego ściągamy plik
adresURL:= Edit1.Text;
{zmienna z nazwą pliku jaka ma być po ściągnięciu
- można wyciągnąć nazwe pliku z adresu URL}
nazwaPliku:= Edit2.Text;
//pobieramy rozmiar pliku jeżeli coś już ściągaliśmy...
if FileExists(nazwaPliku) then
begin
AssignFile(plik, nazwaPliku);
Reset(plik, 1);
rozmiarPliku:= FileSize(plik); //pobieramy rozmiar pliku
Seek(plik, FileSize(plik)); //ustawiamy skażnik na końcu pliku
end
else
begin
AssignFile(plik,nazwaPliku);
ReWrite(plik, 1);
end;
Try
//łączymy się z serwerem...
Label1.Caption:='Łączenie...';
Application.ProcessMessages;
inOpen:= InternetOpen('Mozilla',PRE_CONFIG_INTERNET_ACCESS,nil,nil,0);
inURL:= InternetOpenURL(inOpen,PChar(adresURL),'Accept: */*', StrLen('Accept: */*'),0,0);
if not (inURL <> nil) then
begin
ShowMessage('Nie można uzyskać połączenia');
Stop:= True;
InternetCloseHandle(inURL);
InternetCloseHandle(inOpen);
CloseFile(plik);
Exit;
end;
//pobieramy całkowity rozmiar pliku znajdującego sie na serwerze...
dwIndex:= 0;
dwBufLen:= 1024;
GetMem(Buf, dwBufLen);
HttpQueryInfo(inURL, HTTP_QUERY_CONTENT_LENGTH,buf, dwBufLen,dwIndex);
//ustawiamy progresy (paski postępu)
rozmiar:= StrToInt(StrPas(Buf));
Caption:= 'Rozmiar pliku do ściągnięcia: '+ IntToStr(rozmiar);
ProgressBar1.Max:= rozmiar;
ProgressBar1.Position:= rozmiarPliku;
{ ustawiamy wskażnik pliku znajdującego się na serwerze, czyli
ustalamy od jakiego miejsca w pliku rozpoczynamy pobieranie }
if rozmiarPliku > 0 then InternetSetFilePointer(inURL,rozmiarPliku,nil,0,0);
//pobieranie pliku z serwera...
Label1.Caption:='Ściąganie pliku...';
while (ileZnakow <> 0) and (Stop = false) do
begin
InternetReadFile(inURL, @bufor, SizeOf(bufor),ileZnakow);
InternetQueryDataAvailable(inURL,rozmiar, 0, 0);
BlockWrite(plik, bufor,ileZnakow);
sciagnieto:= FileSize(plik);
Label2.Caption:='Ściągnięto '+ IntToStr(sciagnieto);
ProgressBar1.Position:= sciagnieto;
Application.ProcessMessages;
end;
except
ShowMessage('Wystąpił błąd podczas ściągania pliku !');
Stop:= True;
InternetCloseHandle(inURL);
InternetCloseHandle(inOpen);
CloseFile(plik);
Exit;
end;
Stop:= False;
InternetCloseHandle(inURL);
InternetCloseHandle(inOpen);
CloseFile(plik);
if ProgressBar1.Position = ProgressBar1.Max then
Label1.Caption:= 'Plik został ściągnięty'
else Label1.Caption:= 'Zatrzymane ściąganie pliku';
Beep;
End;
//zatrzymanie pobierania...
PROCEDURE TForm1.btnZatrzymajClick(Sender: TObject);
begin
Stop:= true;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text:= 'http://www.almdev.com/prods/baseskins_compress.zip';
Edit2.Text:= 'ściągnięty plik.zip';
end;
END.
Wiem że wątek stary, ale może ktoś ma pojęcie jak sprawdzić czy plik wogóle istnieje ? Bazując na tym artykule zrobiłem kod który sciaga plik , ale ściaga zawsze, nawet jak link jest zły, to ściaga html'a o tym ze nie ma pliku...Prosze o odpowiedź
Niestety kod nie działa jak należy. Przykład: przerwiemy pobieranie pliku, wyłączymy program a następnie załączymy go ponownie i zechcemy wznowić pobieranie. Program się zawiesi (w tle pobiera plik od nowa) i ruszy dopiero wtedy, gdy zacznie sciągać tego co jeszcze nie pobrał. Bezsens bo równie dobrze można pobrać od nowa. Implementacja ContentRange też mi nie działa.
Dlaczego Aplikacja zawiesza sie kiedy przerwie sie pobieranie a potem sie je wznowi??
Czy ktoś wie skąd pobrać moduł MSHtml ?
Piszę przeglądarkę i nie umiem go znaleść.
Myślę, że aby wyświetlić aktualny transfer ściąganego pliku należy:
a) wyświetla rzeczywisty transefer będący różnicą: Rzeczywisty_Transfer=DTransfer - DLatest;
b) kopiuje wartość aktualnej zmiennej Transfer: DLatest:=DTransfer;
Należy pamiętać, aby DTransfer i DLatest były typu Double, gdyż Int64 może okazać się za mały przy ściąganiu dużych plików, czego konsekwencją może być przekręcenie licznika i wykazanie niebotycznego transferu :-)
Ciekawą kwestią jest ściąganie pliku z możliwie maksymalnym transferem. Podejrzewam, że trzeba odpowiednio dostosować bufor, który w omawianym przykładzie wynosi 1024 bajty, teoretycznie im większy bufor tym szybszy transfer pod warunkiem, że nie przekracza on znacząco wielkości ścągniętej porcji danych, bo wtedy zapisanie bufor'a(u) na dysk fizyczny wstrzymywane jest do czasu wypełnienie całej tablicy bajtami. Większy bufor dłużej się zapisuje i zamiast przechwytywać kolejną porcję danych tracony jest czas na zapis dużego bufora. Znowuż zbyt mały bufor wymaga więcej obrótów pętli i naturalnie znacznie więcej czasu. Reasumując lepiej więcej niż mniej, ale nie za dużo :-)
Czy wie ktoś jak w tym przypadku wysietlić szybkość transferu podczas sciągania?
Przyda mi się :)
spoko art. tego szukałem....:)
Dobre, mysle ze sie moze bardzo przydac :)
super rzecz! tylko nazwij archiwum jakoś inaczej
tylko, że NIC NIE DZIAŁA !!!!!!!!!!!!!!
wow to lubie, konkrety...