2013-12-06 4 views
3

Я следующий код, который делает загрузить файл из Интернета и сохраняет его где-то:счетные хэши на лету во время загрузки

class Foo 
{ 
    private static Uri _url; 
    private static string _filepath; 
    public static void Main(string[] args) 
    { 
     _url = new Uri("http://www.speedtest.qsc.de/1MB.qsc"); 
     _filepath = Environment.CurrentDirectory + "/" + Path.GetFileName(_url.LocalPath); 
     using (var wc = new WebClient()) 
     {     
      wc.DownloadFileCompleted += _bar; 
      wc.DownloadFileAsync(_url, _filepath);    
     } 
     Console.ReadKey(); 
    } 

    private static void _bar (object sender, AsyncCompletedEventArgs e) 
    { 
     using (var md5 = MD5.Create()) 
     { 
      using (var stream = File.OpenRead(_filepath)) 
      { 
       md5.ComputeHash(stream); 
       Environment.Exit(0); 
      } 
     } 
    } 
} 

Я хотел бы вычислить MD5 и SHA1 для файла. Я могу сделать это легко, открыв FileStream после завершения загрузки и используя это для вычисления хэша. Однако это довольно неэффективно для больших файлов.

Что я действительно хотел бы сделать, это рассчитать их уже во время загрузки, обновив хеш после того, как был получен новый блок байтов (с помощью метода TransformBlock).

Есть ли какое-то событие в WebClient, на которое я могу подписаться, чтобы получить байтовые блоки, а затем обновить оба хэша? Должен ли я использовать какой-то другой класс, например WebRequest? Мне нужно также общее количество байтов для чтения, чтобы отобразить некоторую информацию о ходе загрузки.

Спасибо!

ответ

1

Для этого вам, вероятно, следует использовать HttpWebRequest.

Идея заключается в том, что вы настроили свой запрос, а затем позвоните по телефону BeginGetResponse. Затем вы начинаете чтение из потока ответов и хранения в файл. Когда вы получаете каждый блок и перед отправкой его в файл, вы можете использовать данные для вычисления хэша.

На странице MSDN для BeginGetResponse показано, как это сделать для HTML-страницы. Вы изменили бы это немного, чтобы прочитать данные как двоичные, а не текстовые, а вместо добавления к StringBuilder, вы должны записать данные в файл.

Если то, что вы загружаете, достаточно мало, чтобы удобно вместить в память, вы можете использовать WebClient.DownloadDataAsync, а затем вычислить хэш из этого блока памяти, прежде чем сохранять его в файл.

+0

Я закончил использование 'ResponseStream'' WebRequest' и прочитал куски в цикле с 'await remoteStream.ReadAsync' (+' TransformBlock', как упоминалось выше) вместо ручных обратных вызовов, но ваш ответ прав курс. – marce

Смежные вопросы