Sťahovanie súborov z internetu pomocou C/C++
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Sťahovanie súborov z internetu pomocou C/C++Sťahovanie súborov z internetu pomocou C/C++

 

Sťahovanie súborov z internetu pomocou C/C++

Google       Google       7. 3. 2010       24 846×

Jednoduché riešenie pre vaše programy, ktoré potrebujú sťahovať súbory z Internetu. Ak ste uvažovali o rozšírení svojej aplikácie alebo minimálne vašich vedomostí o možnosť sťahovať dáta z Internetu pomocou C++, tak po prečítaní tohto článku by vám to nemalo robiť problém.

Reklama
Reklama

K dosiahnutiu tohto cieľa existuje viacero ciest, no pre programátorov v prostredí Windows je najefektívnejšie využiť WinInet. Dôvody, prečo je tomu tak, v krátkosti objasním.

K súborom, ktoré sa nachádzajú v sieti Internet, sa najčastejšie pristupuje pomocou protokolu HTTP. HTTP teda slúži na výmenu dát medzi klientom a serverom. Nachádza sa na 4.  (aplikačnej) vrstve TCP/IP modelu. Pod ním sa nachádza vrstva transportná, sieťová a fyzická. HTTP je závislé na TCP (Transmission Control Protocol), ktoré je svojim protokolom náročné na aplikovanie. WinInet sa však stará o tieto problémy za nás, a nám sa tak ponúka komfortné implementovanie HTTP služieb.

Samotný postup sťahovania dát z Internetu pomocou WinInet sa skladá z niekoľkých krokov. Prvým z nich je nadviazanie spojenia, resp. vytvorenie inštancie, ktorá sa použije pri otváraní internetových súborov, alebo ešte inak povedané, inicializovanie WinInet pre použitie v aplikácii. Druhým krokom je otvorenie internetového súboru a tretím samotné prečítanie tohto súboru. Tieto tri základné kroky sú však v tomto článku rozšírené, aby sme si ukázali postupy, ktoré je vhodné dodržať. Napríklad zistenie statusu práve otvoreného internetového súboru nie je nutné, no môže nám povedať, či sa daný súbor otvoril, zistiť jeho veľkosť a iné, i keď menej dôležité informácie.

Začal by som popisom jednotlivých funkcií, ktoré v tomto programe použijeme. WinInet obsahuje množstvo užitočných funkcií, no rád by som vám poskytol len základy, na ktorých sa môžete realizovať a rozvíjať. Pre viac informácií môžete navštíviť referencie na MSDN.

  • Prvou takou funkciou, ktorú v našom programe použijeme je:
    DWORD InternetAttemptConnect(DWORD rezervovane);
    Ako už z názvu vyplýva, táto funkcia sa pokúsi o spojenie s Internetom. Lepšie túto funkciu popísať neviem, no na MSDN je trochu presnejší popis, i keď jej úloha nie je až také podstatné, program by fungoval aj bez nej, ale vždy je lepšia prevencia než liečba . Funkcia vracia ERROR_SUCCESS pri úspešnom spojení.
  • HINTERNET InternetOpen(LPCTSTR agent,DWORD typPristupu,LPCTSTR nazovProxy,LPCTSTR proxyBypass,DWORD priznaky);
    Touto funkciou inicializujeme našu aplikáciu na používanie WinInet funkcií. Pri úspešnom inicializovaní obdržíme handler, ktorý sa bude ďalej používať napr. otváraní internetových súborov. agent predstavuje názov vášho agenta, typPristupu je spôsob, akým budeme pristupovať na Internet, resp. či sa bude používať proxy atď. S týmto súvisia aj ďalšie parametre, a to proxyBypass a priznaky.
  • HINTERNET InternetOpenUrl(HINTERNET hInternet,LPCTSTR url,LPCTSTR hlavicky,DWORD dlzkaHlaviciek,DWORD priznaky,DWORD_PTR kontext);
    Otvoríme požadovaný súbor pomocou URL, či už HTTP alebo FTP. My však v tomto programe budeme používať HTTP. Ako hInternet použijeme hodnotu vrátenú funkciou InternetOpen. Parametrom hlavicky špecifikujeme vlastné hlavičky, ktoré sa odošlú spolu s požiadavkou. Funkcia nám vracia handle na otvorený internetový súbor (skôr sa stretnete s pojmom resource).
  • BOOL InternetReadFile(HINTERNET internetovySubor,LPVOID zasobnik,DWORD pocetBajtovNaPrecitanie,LPDWORD pocetPrecitanychBajtov);
    Touto funkciou prečítame určitú časť nášho internetového súboru, resp. v tomto prípade už odpoveď servera. internetovySubor nám určuje, ktorú resource ideme čítať. Tento parameter sme dostali funkciou InternetOpenUrl. Ostatné parametre sú známe. Výsledok funkcie je buď true alebo false. Výsledok true dostaneme aj vtedy, keď sme súbor už prečítali, čiže musíme kontrolovať počet bajtov, ktoré táto funkcia z resource prečítala, a ak sa táto hodnota rovná nule, ukončiť čítanie.
  • BOOL HttpQueryInfo(HINTERNET request,DWORD typInformacie,LPVOID zasobnik,LPDWORD velkostZasobnika,LPDWORD index);
    Túto funkciu môžeme použiť, ak chceme z odpovede servera získať informáciu napr. o statuse odpovede, veľkosti obsahu a pod. Za request v našom prípade dosadíme handle vrátený funkciou InternetOpenUrl. typInformacie nám určuje, ktorú informáciu chceme z hlavičky prečítať. Kompletný zoznam je na MSDN. Do premennej na adrese zasobnik sa uloží výsledok.
//---------------------------------------------------------------------------------
// Sťahovanie súborov z internetu pomocou WinInet
//---------------------------------------------------------------------------------
#include 
#include 
#include 
#include 
#include    // hlavičkový súbor knižnice WinInet
//---------------------------------------------------------------------------------
#define VELKOST_VYROVNAVACEJ_PAMATE   256   // veľkosť vyrovnávacej pamäte použitej
                              // pri čítaní internetového súboru
//---------------------------------------------------------------------------------
#pragma comment(lib,"WinInet.lib")   // prilinkovanie knižnice WinInet
//---------------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------------

int main(int argc, char * argv[])
{
   cout << "Stahovanie suborov z internetu" << endl;
   string url,subor;
   cout << "Zadajte URL suboru: ";
   getline(cin,url);
   cout << "Zadajte nazov suboru na ulozenie: ";
   getline(cin,subor);

   // V prvom rade si deklarujeme premenné, ktoré budeme používať
   HINTERNET spojenie,internetovySubor;
   // Ďalej sa pokúsime o spojenie
   if (InternetAttemptConnect(0) != ERROR_SUCCESS)
   {
      // Spojenie nie je možné nadviazať, resp. nie je možné pracovať v online móde
      cout << "Nebolo mozne sa pokusit o spojenie" << endl;
      cout << "Kod chyby: " << GetLastError() << endl;
      return 1;
   }
   // Teraz si vytvoríme spojenie, inicializujeme aplikáciu na používanie WinInet
   spojenie = InternetOpenA("Moj internetovy prehladavac",
                     INTERNET_OPEN_TYPE_PRECONFIG,   // Predvolené nastavenia
                     0,                        // Žiadne proxy
                     0,                        
                     0);                        // Žiadne príznaky
   if (spojenie == 0) // NULL
   {
      cout << "Nie je mozne inicializovaz WinInet" << endl;
      cout << "Kod chyby: " << GetLastError() << endl;
      return 1;
   }
   // Následne otvoríme spojenie so súborom, ktorý je definovaný pomocou URL
   internetovySubor = InternetOpenUrlA(spojenie,      // Inštancia spojenia
                              url.c_str(),   // URL adresa súboru
                              0,            // Žiadna prídavná HTTP hlavička
                              0,            // Dĺžka prídavnej hlavičky   
                              0,            // Žiadne príznaky
                              0);
   if (internetovySubor == 0) // NULL
   {
      cout << "Nie je mozne vytvorit spojenie so suborom" << endl;
      DWORD kodChyby = GetLastError();
      cout << "Kod chyby: " << kodChyby << endl;
      char chyba[256];
      DWORD chybaVelkost = 255;
      if (InternetGetLastResponseInfoA(&kodChyby,chyba,&chybaVelkost))
         cout << "Popis chyby: " << chyba << endl;
      // Nesmieme zabudnúť zatvoriť už inicializovaný handler s WinInet
      InternetCloseHandle(spojenie);
      return 1;
   }
   // V tomto kroku môžeme zistiť podrobnosti o súbore
   DWORD informacia;
   DWORD velkostInformacie = sizeof(DWORD);
   // Najskôr si zistíme HTTP status kód (napr. status kód 200 znamená OK, 404 znamená súbor nenájdený)
   if (!HttpQueryInfoA(internetovySubor,   // Inštancia nami vytvoreného spojenia so súborom
               HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,   // Požadujeme status ktorý je číselným typom
               &informacia,         // Sem bude zapísaný výsledok volania
               &velkostInformacie,      // Veľkosť dátovej jednotky informácie
               0))
   {
      cout << "Nie je mozne zistit kod statusu" << endl;
      cout << "Kod chyby: " << GetLastError() << endl;
      InternetCloseHandle(internetovySubor);
      InternetCloseHandle(spojenie);
      return 1;
   }
   cout << "Status odpovede: " << informacia << endl;
   // Ak sa status odpovede nerovná 200, nedostaneme súbor, ktorý sme požadovali
   if (informacia != HTTP_STATUS_OK)
   {
      cout << "Status spojenia NIE je OK" << endl;
      InternetCloseHandle(internetovySubor);
      InternetCloseHandle(spojenie);
      return 1;
   }
   // Teraz si zistíme veľkosť súboru
   if (!HttpQueryInfoA(internetovySubor,   // Inštancia nami vytvoreného spojenia so súborom
               HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,   // Požadujeme status ktorý je číselným typom
               &informacia,         // Sem bude zapísaný výsledok volania
               &velkostInformacie,      // Veľkosť dátovej jednotky informácie
               0))
   {
      // Síce sme nezistili veľkosť súboru, ale to nám neprekáža v jeho stiahnutí
      cout << "Velkost suboru sa neda zistit" << endl;
      informacia = 0;
   }
   // Vytvoríme si vyrovnávaciu pamäť, do ktorej budeme ukladať časti súboru
   char * vyrovnavaciaPamat = new char[VELKOST_VYROVNAVACEJ_PAMATE];
   // Vytvoríme si výstupný súbor
   fstream vystupnySubor(subor.c_str(),   // Názov výstupného súboru
                  ios_base::out | ios_base::binary);   // Budeme zapisovať v binárnom móde
   // Premenná, do ktorej sa bude ukladať koľko sme z internetového súboru prečítali
   DWORD precitane = 0;
   // Premenná, do ktorej uložíme celkový počet stiahnutých bajtov
   DWORD stiahnute = 0;

   cout << "Stahujem\t\t\t";
   while (InternetReadFile(internetovySubor,   // Spojenie na náš internetový súbor
                     vyrovnavaciaPamat,   // Vyrovnávacia pamäť
                     VELKOST_VYROVNAVACEJ_PAMATE,   // Koľko môžeme max. prečítať
                     &precitane))      // Koľko WinInet prečítal
   {
      if (precitane == 0)      // Už sme všetko prečítali, ukončiť
         break;
      stiahnute += precitane;
      if (informacia != 0)   // Ak vieme o veľkosti súboru môžeme vypočítať %
         cout << "\rStahujem " << (int)((stiahnute*100)/informacia) << "%";
      else               // Inak len vypíšeme celkový počet stiahnutých B
         cout << "\rStahujem " << stiahnute << " B";
      // Zapísať do vsýtupného súboru
      vystupnySubor.write((const char*)vyrovnavaciaPamat,precitane);
   }
   cout << endl << endl;
   // Zistíme chybu (ak nejaká nastala)
   DWORD chyba = GetLastError();
   if (chyba != 0)
   {
      cout << "Pri citani vznikla chyba" << endl;
      cout << "Kod chyby: " << chyba << endl;
      char chybaText[256];
      DWORD chybaVelkost = 255;
      if (InternetGetLastResponseInfoA(&chyba,chybaText,&chybaVelkost))
         cout << "Popis chyby: " << chyba << endl;
   }
   else
   {
      cout << "Hotovo" << endl;
   }
   // Zatvoríme spojenia
   InternetCloseHandle(internetovySubor);
   InternetCloseHandle(spojenie);
   // Zatvoríme výstupný súbor
   vystupnySubor.close();
   // Nezabudneme vyrovnávaciu pamäť uvoľniť :)
   delete [] vyrovnavaciaPamat;
   return 0;
}

Už funkčný exe súbor spolu s kódom nájdete na: http://router.xf.cz/cppfiledownload.zip

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
Autor sa venuje programovaniu v jazykoch C#, C/C++, Delphi a v poslednej dobe sa taktiež zaujíma o vývoj hardvéru.
Web    

Nové články

Obrázek ke článku Nový IT hráč na českém trhu

Nový IT hráč na českém trhu

V roce 2015 otevřela v Praze na Pankráci v budově City Tower své kanceláře společnost EPAM Systems (NYSE:EPAM), jejíž centrála se nachází v USA. Společnost byla založená v roce 1993 a od té doby prošla velkým vývojem a stále roste.

Reklama
Reklama
Obrázek ke článku České Radiokomunikace opět hledají nejlepší nápady pro internet věcí

České Radiokomunikace opět hledají nejlepší nápady pro internet věcí

České Radiokomunikace (CRA) pořádají druhý ročník CRA IoT Hackathonů. Zájemci z řad vývojářů a fanoušků moderních technologií mohou změřit své síly a během jediného dne sestrojit co nejzajímavější funkční prototyp zařízení, které bude komunikovat prostřednictvím sítě LoRa. CRA IoT Hackathony se letos uskuteční ve dvou fázích, na jaře a na podzim, v různých městech České republiky. Jarní běh se odstartuje 31. března v Brně a 7. dubna v Praze.

Obrázek ke článku Cloud computing je využíván stále intenzivněji

Cloud computing je využíván stále intenzivněji

Využívání cloud computingu nabývá na intenzitě. Jen v letošním roce vzroste podle analytiků trh se službami veřejného cloudu o 18 %, přičemž o téměř 37 % vzrostou služby typu IaaS. Růst o více než pětinu pak čeká služby poskytování softwaru formou služby, tedy SaaS. Aktuálním trendům v oblasti využívání cloudu se bude věnovat konference Cloud computing v praxi, která se koná 23. března. 2017 v pražském Kongresovém centru Vavruška na Karlově náměstí 5.

loadingtransparent (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();
Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032017 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý