TP

.NET - Stahování souborů z internetu

Co tento článek ukazuje

Ukázková aplikace

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

Published: Sunday, 9 April 2006, 1:42 PM
Author: Tomas Petricek
Typos: Send me a pull request!
Tags: