Panowanie nad szybkością ściagania pliku

0

Witam.

Poniżej standardowa procedura do ściągania pliku, która chciałbym usprawnić,
mam nadzieję że nie przestarzała, ale u mnie się na razie sprawdza.
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 B/s?

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;

0

Mierzysz czas ściągnięcia kolejnego bloku, rozmiar bloku znasz, więc łatwo wyliczyć prędkość.
Aby ją ograniczyć wstaw pętle do określonego czasu z Application.ProcessMessages.

0

Application.ProcessMessages próbowałem zastosować po odczytaniu z serwera i po zapisaniu na dysku, żeby nie tracić kontroli nad aplikacją ale powiedzmy w 30% przypadków wywoływało błąd dlatego szukam innego sposobu. Podejrzewam że bez wątków się nie obejdzie ale jest jeszcze sprawa jak już na poziomie pobierania danych sprawdzać czy nie ma problemów z internetem, co bajt sprawdzać czy jest połączenie, ma to sens?

0

Nie ma sensu, wystarczy try except end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1