CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Najprostszy sposób na pobranie pliku z internetu

Najprostszy sposób na pobranie pliku z internetu

problemy z tworzeniem programów do obsługi sieci, internetu, e-mail itp..

Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez unloco » poniedziałek, 24 grudnia 2012, 00:01

Witam. Spędziłem dzisiaj parę godzin na szukaniu rozwiązania mojego problemu:

Otóż planuję sobie napisać program, który ściągnie mi z internetu wybrany plik.

Założenia:

Wpisuję adres internetowy w pole TEdit i wciskam buttona.
Pojawia mi się okienko gdzie chcę zapisać plik (TOpenDialog zapewne trzeba wykorzystać, jak mniemam).
Miłoby było, gdyby ktoś jeszcze podpowiedział jak tutaj zastosować pasek postępu, ale nie jest to konieczne

Opcjonalnie w pola Edit1 i Edit2 mogę wpisać login i hasło, jeśli jest konieczne, aby ściągnąć plik.

Kombinowałem sam, na google znalazłem http://www.programuj.com/forum/viewtopic.php?p=14576 (ostatni listing - użytkownika PabloX), ale pojawia mi się error: Connection Timed out.

Proszę o pomoc. Jestem w kropce.
Avatar użytkownika
unloco
Bladawiec
Bladawiec
 
Posty: 5
Dołączył(a): niedziela, 23 grudnia 2012, 23:34
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Win 7
Kompilator: C++ Builder 2007
Gadu Gadu: 2154588
    Windows 7Chrome

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Cyfrowy Baron » poniedziałek, 24 grudnia 2012, 12:05

Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4727
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Mironas » poniedziałek, 24 grudnia 2012, 12:37

unloco napisał(a):TOpenDialog zapewne trzeba wykorzystać, jak mniemam.

Nie TOpenDialog tylko TSaveDialog, przecież chcesz zapisać plik na dysku, a nie otworzyć go.

Do przykładów Cyfrowego Barona dodałbym jeszcze pobieranie pliku za pomocą TIdHTTP (z pakietu Indy):
KOD cpp:     UKRYJ  
  if ( SaveDialog1->Execute() )
  {
    TMemoryStream* strm = new TMemoryStream();
    IdHTTP1->Get(Edit1->Text, strm);
    strm->SaveToFile(SaveDialog1->FileName);
    delete strm;
  }
 


A jeśli do tego chcesz pokazać proces pobierania na pasku to masz do tego takie zdarzenia komponentu TIdHTTP:
KOD cpp:     UKRYJ  
void __fastcall TForm1::IdHTTP1WorkBegin(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax)
{
  ProgressBar1->Position = 0;
  ProgressBar1->Max = AWorkCountMax;
  Application->ProcessMessages();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdHTTP1Work(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount)
{
  ProgressBar1->Position = AWorkCount;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdHTTP1WorkEnd(TObject *ASender, TWorkMode AWorkMode)
{
  ShowMessage("Pobrano!");
}
//---------------------------------------------------------------------------
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 446
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 21
Otrzymał podziękowań: 63
System operacyjny: Windows 10
Kompilator: C++Builder 10.2 Tokyo
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez _wędkarz_ » wtorek, 1 stycznia 2013, 22:12

Pozwolę sobie podłączyć się do tematu.
Muszę pobrać kursy walut, znalazłem taką stronę, wydaje się najbardziej odpowiednia. http://nbp.pl/Kursy/KursyA.html
I tu moje pierwsze pytanie, dane wyciągać jakoś z html tej strony czy ściągać te dane w xml(na dole strony jest taka możliwość)
Kursy da się jakoś wyciągnąć na internecie czy muszę ściągnąć plik na kompa? Tutaj zastosować albo IdHTTP lub urlmon.h a może coś innego?
Jak potem to wyszukać? Jeśli z html to może po numerze wiersza i wtedy jakoś ten kurs wyciągnąć? czy może jakis parser XML(nic o tym nie wiem, tylko słyszałem) w necie znalazłem jakiś TinyXML
Avatar użytkownika
_wędkarz_
Bladawiec
Bladawiec
 
Posty: 8
Dołączył(a): niedziela, 30 grudnia 2012, 10:33
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: CodeBlocks, BCB 6
Gadu Gadu: 0
    Windows 7Firefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Cyfrowy Baron » wtorek, 1 stycznia 2013, 22:24

Niezależnie od wybranego sposobu musisz albo pobrać plik XML a potem go parsować - w C++Builder 6, chyba nie ma do tego bibliotek, albo musisz wczytać źródło strony i też je parsować. Źródło strony można wczytać od razu do pamięci, czyli wczytać podobnie jak to robi przeglądarka.
Zapoznaj się z tym tematem: Wyciąganie adresów URL ze stron internetowych. - Musisz stworzyć coś podobnego, ale nie do wyciągania adresów lecz innych potrzebnych informacji.
Przydałyby się tutaj regex'y, ale nie będę ci tego komplikował.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4727
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez polymorphism » wtorek, 1 stycznia 2013, 23:13

czy może jakis parser XML

Najsensowniej. Po to zresztą udostępniają to w XML-u, żeby można było sobie te dane jakość sensownie pobrać i poddać dalszej obróbce.

w necie znalazłem jakiś TinyXML

Powinien wystarczyć. Jest to prosta w instalacji i użyciu biblioteka.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2187
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 204
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Darek_C++ » środa, 2 stycznia 2013, 11:57

Możesz parsować za pomocą TinyXML lub wyrażeń regularnych i Boost.Regex. Możesz też wyciągając dane posługując się metodami klasy AnsiString jak Pos, Delete, SubString wyciągając coraz mniejsze bloki danych z danej struktury danych.

Jeśli chcesz pobierać z XML'a musisz najpierw pobrać adres do XML'a z http://nbp.pl/Kursy/KursyA.html na dole masz link:
<p class="file print_hidden"><a href="/kursy/xml/a252z121231.xml" target="_blank">Powyższa tabela w formacie .xml</a></p>
Jak chodzi o pobieranie:
Mironas napisał(a):
unloco napisał(a):TOpenDialog zapewne trzeba wykorzystać, jak mniemam.

Do przykładów Cyfrowego Barona dodałbym jeszcze pobieranie pliku za pomocą TIdHTTP (z pakietu Indy):

rób to w osobnym wątku, bo w wypadku większego pliku, lub wolnego łącza / serwera będziesz miał blokowanie całego programu co dosyć kiepsko wygląda w praktyce.
I jeszcze jedno metoda
KOD cpp:     UKRYJ  
IdHTTP1->Get(Edit1->Text, strm);
może generować wyjątki które powinieneś obsłużyć :)
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Mironas » środa, 2 stycznia 2013, 12:24

Darek_C++ napisał(a):
Mironas napisał(a):Do przykładów Cyfrowego Barona dodałbym jeszcze pobieranie pliku za pomocą TIdHTTP (z pakietu Indy):

rób to w osobnym wątku, bo w wypadku większego pliku, lub wolnego łącza / serwera będziesz miał blokowanie całego programu co dosyć kiepsko wygląda w praktyce.


Można też dodać na formę TIdAntiFreeze oraz dodać Application->ProcessMessages(); do IdHTTP1Work:
KOD cpp:     UKRYJ  
void __fastcall TForm1::IdHTTP1Work(TObject *Sender, TWorkMode AWorkMode,
      const int AWorkCount)
{
  ProgressBar1->Position = AWorkCount;
  Application->ProcessMessages();
}
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 446
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 21
Otrzymał podziękowań: 63
System operacyjny: Windows 10
Kompilator: C++Builder 10.2 Tokyo
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez polymorphism » środa, 2 stycznia 2013, 12:53

Darek_C++ napisał(a):Jeśli chcesz pobierać z XML'a musisz najpierw pobrać adres do XML'a z http://nbp.pl/Kursy/KursyA.html na dole masz link:
<p class="file print_hidden"><a href="/kursy/xml/a252z121231.xml" target="_blank">Powyższa tabela w formacie .xml</a></p>

Nie musi tego robić, ponieważ NBP udostępnia bezpośredni dostęp do pliku XML -> http://nbp.pl/Kursy/xml/LastA.xml
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2187
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 204
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Cyfrowy Baron » środa, 2 stycznia 2013, 19:21

Oto przykładowy kod pobierający kursy walut z pliku LastA.xml bezpośrednio z internetu bez ściągania pliku na dysk i bez konieczności stosowania dodatkowych bibliotek. Cały kod zawarłem w pliku źródłowym:

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#include "wininet.h"
#include "memory"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

#pragma link "Wininet.lib"

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

AnsiString ReadFileURL(AnsiString Url)
{
 AnsiString result = "";
 HINTERNET hSession = NULL;
 hSession = InternetOpenA("ReadFileURL", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
 if(hSession)
 {
  HINTERNET hService = NULL;
  hService = InternetOpenUrlA(hSession, Url.c_str(), NULL, 0, 0, 0 );
  if(hService)
  {
   while(1)
   {
        char lpBuffer[1024 + 1];
        DWORD dwBytesRead;
        InternetReadFile(hService, lpBuffer, 1024, &dwBytesRead);
    if(dwBytesRead == 0) break;
    lpBuffer[dwBytesRead] = 0;
    result += lpBuffer;
   }
  }
  InternetCloseHandle(hService);
 }
 InternetCloseHandle(hSession);
 return result;
}
//---------------------------------------------------------------------------
AnsiString NazwaWaluty(AnsiString Value)
{
 int start = Value.Pos("<nazwa_waluty>") + 14;
 int end = Value.Pos("</nazwa_waluty>") - start;

 return Value.SubString(start, end);
}
//---------------------------------------------------------------------------
AnsiString Przelicznik(AnsiString Value)
{
 int start = Value.Pos("<przelicznik>") + 13;
 int end = Value.Pos("</przelicznik>") - start;

 return Value.SubString(start, end);
}
//---------------------------------------------------------------------------
AnsiString KodWaluty(AnsiString Value)
{
 int start = Value.Pos("<kod_waluty>") + 12;
 int end = Value.Pos("</kod_waluty>") - start;

 return Value.SubString(start, end);
}
//---------------------------------------------------------------------------
AnsiString KursSredni(AnsiString Value, int &pos)
{
 int start = Value.Pos("<kurs_sredni>") + 13;
 int end = Value.Pos("</kurs_sredni>") - start;

 pos = end + start + 13;

 return Value.SubString(start, end);
}
//---------------------------------------------------------------------------
std::auto_ptr<TStringList> GetExchangeRates(AnsiString Url)
{
 AnsiString Value = ReadFileURL( Url );

 std::auto_ptr<TStringList> Result (new TStringList);

 int pos = 14;

 while( pos > 13 )
 {
  Result->Add( NazwaWaluty( Value) + " - " +
               Przelicznik( Value ) + " - " +
               KodWaluty( Value ) + " - " +
               KursSredni( Value, pos)
                         );

  Value = Value.Delete(1, pos);
 }

 Result->Delete( Result->Count - 1 ); /* kasuje ostatni pusty wiersz */
 return Result;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 Screen->Cursor = crHourGlass;

 Memo1->Lines->Assign( GetExchangeRates("http://nbp.pl/Kursy/xml/LastA.xml").get() );

 Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------



Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4727
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez _wędkarz_ » środa, 2 stycznia 2013, 23:33

OK, kod już rozszyfrowałem i powoli przyswajam do łba co by w przyszłości móc samemu napisać(ten też oczywiście kod zmienię, gdyż potrzebuję tylko kilku walut i żeby one były przypisane do zmiennej i wyświetlone w tablicy ale to myślę, że nie będzie już dla mnie problem).
KOD cpp:     UKRYJ  
AnsiString KodWaluty(AnsiString Value)
{
 int start = Value.Pos("<kod_waluty>") + 12; //Tutaj +12 jest po to, żeby przeszukiwało wiersz, który ma zawartość"<kod_waluty>" dopiero od 12 znaku??
 int end = Value.Pos("</kod_waluty>") - start; // tutaj ma nam przeszukiwać wiersz, który ma zawartość"</kod_waluty>"  ale wyłaczając zmienną start czyli pierwsze 12 znaków??

 return Value.SubString(start, end); // tutaj polecenie które mam nam zwrócić to co jest pomiędzy właśnie startem a endem?
}
//---------------------------------------------------------------------------

 
Czemu deklaracja jest jako int? Chodzi o to że wartość jest przechowywana jako kod binarny? Bo nie mam pojęcia tutaj
KOD cpp:     UKRYJ  
AnsiString KursSredni(AnsiString Value, int &pos) //  "int &pos" chodzi tutaj o adres wskaźnika?
{
 int start = Value.Pos("<kurs_sredni>") + 13;
 int end = Value.Pos("</kurs_sredni>") - start;

 pos = end + start + 13;// o co w tym chodzi? potem jest to też odczytywane w resultacie

 return Value.SubString(start, end);



edit: Jeszcze gdybyś mógł to pokrótce proszę opisz funkcje ReadFileURL
Avatar użytkownika
_wędkarz_
Bladawiec
Bladawiec
 
Posty: 8
Dołączył(a): niedziela, 30 grudnia 2012, 10:33
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: CodeBlocks, BCB 6
Gadu Gadu: 0
    Windows 7Firefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez Cyfrowy Baron » czwartek, 3 stycznia 2013, 05:55

Odnośnie pierwszego kodu - te liczby służą do określenia pozycji w której znajduje się tylko wartość między tagami, a nie wartość plus tagi. Funkcja SubString wycina tekst z wyrażenia i oczekuje jako argumentów początku i końca od którego tekst ma być wycinany przy czym koniec musi uwzględniać pozycję początku stąd end - start. start + 12 gdyż wyrażenie "<kod_waluty>" ma długość 12 znaków, w funcja Pos szuka co prawda tego wyrażenia, ale zwraca pozycję jego początku a nie końca, dlatego gdybym nie zrobił przesunięć to SubString wyciąłby nie tylko kod waluty, ale również tagi - poeksperymentuj.

Dlaczego int &pos, bo przekazuję do funkcji zmienną int pos zadeklarowaną w funkcji GetExchangeRates po to by sterowała pętlą while, po przeszukaniu całego pliku pętla musi się przecież zatrzymać i służy do tego zmienna pos. Niezależnie od tego, czy pobierasz całą tabelę, czy wybrane waluty przeszukać i tak musisz cały plik. W każdym obiegu pętli pos określa pozycję ostatniego wyszukiwanego elementu i z całego pliku usuwa wszystko co jest przed tą pozycją - funkcja Delete(1, pos). W kolejnym obiegu pętli zawartość pliku jest więc już krótsza, gdyż zostało z niego usunięte to co zostało już przeszukane. Gdyby tak nie było funkcja Pos zawsze zatrzymywałaby się na pierwszym elemencie tabeli, gdyż ta funkcja zatrzymuje się na pierwszym znalezionym elemencie.

Co do tego binarnego, to nie wiem skąd ci to przyszło do głowy!?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4727
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez cezarrek » czwartek, 12 marca 2015, 13:06

W jaki sposób można by przerobić kod Cyfrowego Barona, który pobierałby kursy walut, ale według określonej daty
Avatar użytkownika
cezarrek
Bladawiec
Bladawiec
 
Posty: 14
Dołączył(a): poniedziałek, 12 marca 2012, 15:07
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: XP 2002 SP3
Kompilator: BCB 6 Personal
Gadu Gadu: 0
    Windows 7Firefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez polymorphism » czwartek, 12 marca 2015, 13:50

Tu masz opis tego, jak pobierać dane z różnych dat ze strony NBP -> http://www.nbp.pl/home.aspx?f=/kursy/in ... walut.html
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2187
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 204
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows 7Firefox

Re: Najprostszy sposób na pobranie pliku z internetu

Nowy postprzez cezarrek » piątek, 13 marca 2015, 01:20

Cześć raz jeszcze.
Czy pobierałbym bezpośrednio do pamięci czy przepisywał od razu do jakiegoś obiektu lub nawet zapisywał do pliku i potem otwierał to w każdym przypadku wychodzą takie krzaczki i zawsze ma się do pierwszej linii.
A chodzi o ten plik: http://www.nbp.pl/kursy/xml/dir.txt

c001z020102
h001z020102
a001z020102
b001z020102
...
Avatar użytkownika
cezarrek
Bladawiec
Bladawiec
 
Posty: 14
Dołączył(a): poniedziałek, 12 marca 2012, 15:07
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: XP 2002 SP3
Kompilator: BCB 6 Personal
Gadu Gadu: 0
    Windows 7Firefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Aplikacje sieciowe

Kto przegląda forum

Użytkownicy przeglądający ten dział: Google [Bot] i 1 gość

cron