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

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       30 916×

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.

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 Stavebnice umělé inteligence 1

Stavebnice umělé inteligence 1

Článek popisuje první část stavebnice umělé inteligence. Obsahuje lineární a plošnou optimalizaci.  Demo verzi je možné použít pro výuku i zájmovou činnost. Profesionální verze je určena pro vývojáře, kteří chtějí integrovat popsané moduly do svých systémů.

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý