Skocz do zawartości

[Delphi] panowanie nad szybkością ściagania pliku


Integer

Polecane posty

Witam.

 

Poniżej standardowa procedura do ściągania pliku, mam nadzieję że nie przestarzała :)

Szukam informacji na temat jak ograniczyć prędkość ściągania a konkretnie idealne było by:

1. Jak sprawdzić prędkość pobierania z danego stanowiska np. SpeedNet=?B.

2. Jak zabezpieczyć się przed zawieszeniem w trakcje pobierania danych gdy internet padnie.

3. Na koniec jak ściągnąć plik z prędkością +-SpeedNet/10?

 

Zastanawiałem się nad wątkami, ale manewrowanie priorytetami wątków nie jest na tyle precyzyjne,

no i oczywiście jeśli dany wątek ściągający plik wisi to trzeba go umiejętnie kontrolować,

a ja chciałem rozwiązać problem w zarodku ... o ile się da.

 

//Procedura ściąga lub "dociąga" plik z internetu...
function  TNetFtp.SciagnijFile(Sender: TObject; adresURL, FNameZapisu :String): Boolean;
 // adresURL - zmienna z adresem URL z którego ściągamy plik
 // nazwaPliku - {nazwa pliku jaka ma być po ściągnięciu, może być dowolna
var
 plik                                 :File;
 inOpen, inURL                        :HINTERNET;
 HTTPRozmiarPliku, HTTPRozmiarPliku1  :DWORD;
 ileZnakow                            :DWord;
 dwBufLen, dwIndex                    :DWord;
 Sciagnieto, HDRozmiarPliku           :DWord;
 bufor :array[1..1024] of byte;
 buf   :Pointer;

begin
 Result:= False;
 Stop:= false;
 //ustawiamy dane...
 inOpen:= nil;
 inURL:= nil;
 HDRozmiarPliku:= 0;
 HTTPRozmiarPliku:= 0;
 Sciagnieto:= 0;
 // ProgressBar1.Position:= 0;

 // jesli plik o takie j nazwie nie jest dostępny
 if ExistURL(adresURL) = False then begin Result:= False; Exit; end;

 //pobieramy rozmiar pliku jeżeli coś już ściągaliśmy...
 if FileExists(FNameZapisu) then
 begin
   AssignFile(plik, FNameZapisu);
   Reset(plik, 1);
   HDRozmiarPliku:= FileSize(plik); //pobieramy rozmiar pliku
   Seek(plik, FileSize(plik));      //ustawiamy skażnik na końcu pliku
 end
 else
 begin
   AssignFile(plik,FNameZapisu);
   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)
   HTTPRozmiarPliku1:= StrToInt(StrPas(Buf));
   HTTPRozmiarPliku := HTTPRozmiarPliku1;


   //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 HDRozmiarPliku > 0
     then InternetSetFilePointer(inURL, HDRozmiarPliku, 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, HTTPRozmiarPliku, 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 (HDRozmiarPliku = HTTPRozmiarPliku1) or  (Sciagnieto = HTTPRozmiarPliku1)
   then Result:= True
   else Result:= False;

 {
 if ProgressBar1.Position = ProgressBar1.Max then
    // Label1.Caption:= 'Plik został ściągnięty'     // -----------------------
    else Label1.Caption:= 'Zatrzymane ściąganie pliku';
 }
 //Beep;
end;

Link do komentarza
Udostępnij na innych stronach

Jak chcesz ograniczyć prędkość pobierania to poprostuj odczytuj tylko tyle danych ile chcesz w danej jednostce czasu np. chcesz predkosc 1kb/s to stwórz bufor o takiej wielkości i nie pobieraj nowej paczki częsciej niż co 1s.

Co do sprawdzania pedkości pobierania to prawie to samo co wyżej tylko że sprawdzasz jaki upłynął czas przy ściąganiu paczki.

W jaki sposób zabezpieczyć? Jak coś będzie nie tak z połączeniem to pewnie dostaniesz Exceptiona. Najprościej wywalić co się wszystko ściągneło i zacząć od nowa. Tylko niektóre serwery pozwalają na ściąganie od dowolnego miejsca, ale nie wiem jak to się robi pewnie ustala się to w nagłówku HTTP.

 

 

 

 

Jeśli nie zrobisz tego na wątkach to aplikacja ci się zawiesi na czas pobierania pliku a to złe jest. Przy ściąganiu pojednynczych plików można zaprojektować wątek tak, że obejdzie się bez synchronizacji z innymi wątkami, reszta jest już prosta.

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...