.NET - Stahování souborů z internetu
Co tento článek ukazuje
- Stahování textových souboru pomocí třídy WebClient
- Totéž pomocí WebRequest a WebResponse
- Stahování binárních souborů
Občas člověk ve své aplikaci potřebuje stahovat různé soubory (například aktualizace, nové pluginy - viz článek o tvorbě pluginů) z internetu. Může se jednat buď o textové soubory (například html stránky) a nebo o binární soubory. To jak soubor stáhnout a jak s ním dále pracovat bude popsáno v tomto článku.
Třída WebClient
V .NET Frameworku jsou obvyklé operace se soubory na internetu snadno realizovatelné
pomocí standardních objektů, které naleznete v namespace (jmenném prostoru)
System.Net
. Nejjednodušší objekt, pomocí kterého lze stáhnout soubor
z internetu je objekt WebClient
. Jediné co je potřeba udělat, je
zadat objektu adresu souboru, který se má stáhnout a WebClient
vrátí
Stream
pomocí kterého lze stažená data načítat.
(Tento článek předpokládá, že máte povědomí o tom co je Stream a jak s ním
pracovat, pokud ne doporučuji článek o práci se soubory: viz. [1])
// Vytvorit objekt WebClient WebClient wc=new WebClient(); // Otevre stream pro cteni dat ze zadane adresy Stream stream=wc.OpenRead(url); // Nacte obsah celeho souboru do textoveho retezce StreamReader sr=new StreamReader(stream); string ret=sr.ReadToEnd(); // Uzavrit stream sr.Close();
Pokročilejší postup pomocí WebRequest
Výše uvedené stahování souborů pomocí objektu WebClient
je velmi jednoduché,
ale často se může stát, že budete potřebovat něco více než pouze získat
Stream
pro čtení dat. V tomto případě budete potřebovat dvojici tříd
WebRequest
a WebResponse
. Obě třídy jsou abstraktní,
což znamená, že samy o sobě nic nedělají a všechna funkcionalita je v
třídách od nich odvozených - v našem případě budeme tedy potřebovat ještě
odvozenou třídu HttpWebRequest
.
Při práci s těmito třídami si napřed vytvoříme dotaz (objekt odvozený od
WebRequest
) a tento dotaz poté vykonáme a tím získéme odpověď
ze serveru (objekt odvozený od WebResponse
). Oproti předcházející ukázce
umožňuje objekt WebRequest
nastavit mnoho dalších
parametrů pro dotaz na server (lze například nastavit dobu po které se přestane
čekat na server, nebo je možné nastavit různé http hlavičky). Následující
příklad ukazuje jak používat tyto dva objekty (zatím bez dalšího nastavování):
// Vytvori dotaz na server WebRequest request=HttpWebRequest.Create(url); // Ziska odpoved od serveru WebResponse response=request.GetResponse(); // Ziska stream pro cteni dat a nacte data Stream responseStream=response.GetResponseStream(); StreamReader reader=new StreamReader(responseStream); string ret=reader.ReadToEnd(); // Ukoncit komunikaci response.Close();
Jak jsem již psal, tento způsob umožňuje nastavovat mnoho dalších vlastností
pro dotaz. Následující ukázka pracuje přímo s objektem HttpWebRequest
a přidává několik specifických HTTP hlaviček (jediné co se mění oproti
předcházející ukázce je vytváření dotazu).
// Vytvori HTTP dotaz na server HttpWebRequest request=(HttpWebRequest)WebRequest.Create(url); // Nastavi dotazu nejake dalsi vlastnosti request.Referer="http://www.vyvojar.cz"; request.UserAgent="Muj Webovy Prohlizec"; request.Headers.Add("Accept-Language","cs,en"); // Ziska odpoved od serveru a nacte data WebResponse response=request.GetResponse(); // ...
Kódování souboru
S kódováním souborů na internetu byly problémy od doby kdy něco jako kódování
vzniklo a tomuto problému se nevyhnete bohužel ani v .NETu. Pokud v aplikaci
stahujete soubor, který jste sami vytvořili je situace docela snadná, protože
znáte kódování souboru. V tomto případě stačí nastavit kódování jako
parametr objektu StreamReader
, který načítá data z internetu
a ten načte soubor korektně.
// Nacte data se spravnym kodovanim
StreamReader reader=new StreamReader(responseStream,
System.Text.Encoding.GetEncoding("windows-1251"));
string ret=reader.ReadToEnd();
Doposud bylo vše relativně snadné, ale pokud se pokusíte stahovat
libovolnou webovou stránku nevíte dopředu v jakém kódování stránka bude.
Kódování by mělo být možné zjistit z objektu WebResponse
(zkuste se
podívat na vlastnost ContentType
),
ale ani to obecně neplatí. U některých stránek lze kódování zjistit
až z HTML kódu (pomocí tagu meta
), ale abych mohl toto kódování
zjišťovat bude potřeba nejprve načíst stránku do paměti, poté hledat kódování
a nakonec stránku převést do řetězce s použitím příslušného kódování.
To je trošku komplikovanější (a je to mimo rozsah tohoto článku), ale naštěstí
existuje volně dostupný kód, která toto řeší (viz [2]).
Stahování binárních souborů
Pokud budete potřebovat stahovat binární soubor, můžete použít již zmíněný
objekt WebClient
a jeho metodu DownloadData
, která
vrací pole bytů. Pokud ale budete chtít vytvářet dotaz pomocí WebRequest
(a nastavovat více vlastností) nebo budete stahovat velký soubor, který se
nevejde celý do paměti budete muset stažená data kopírovat do souboru postupně,
jak ukazuje poslední ukázka.
Kód funguje tak, že si nejprve vytvoří pomocné pole (buffer
),
do kterého načte vždy maximálně 10kB a takto načtená data uloží do výstupního
souboru. Kopírování se ukončí až když metoda Read
načte 0
bytů a to nastane až po zkopírování celého souboru.
// ... ziska stream pro cteni dat a nacte data Stream responseStream=response.GetResponseStream(); // Vytvori soubor kam se ulozi obsah z internetu Stream writeStream=File.Create("C:\\soubor.bin"); // Zkopirovat data byte[] buffer=new byte[10240]; int bytesRead; while(true) { // pokud nacte 0 bytu tak je zkopirovano vse bytesRead=responseStream.Read(buffer,0,buffer.Length); if (bytesRead==0) break; // ulozit nacteny buffer writeStream.Write(buffer,0,bytesRead); } // Zavrit streamy responseStream.Close(); writeStream.Close();
Soubory na stažení a odkazy
- [1] Práce s obsahem souborů v .NET [^] - Projekt Asp.Net
- [2] Korektní získání obsahu HTML stránky včetně kódování [^] - Michalův zápisníček