Download arquivos grandes em .NET
Introdução
O problema que enfrentamos basicamente é sobre muitas abordagens que vemos por aí, que funciona apenas para arquivos pequenos, que é por exemplo escrever os bytes usando o MemoryStream e depois escrever em um arquivo como demonstrado abaixo:
//...
const string url = "https://ralms.io/poeira_em_alto_mar.mp4";
using (var response = await client.GetAsync(url))
using (var streamContent = await response.Content.ReadAsStreamAsync())
{
string tempFile = Path.GetTempFileName();
using (var streamWrite = File.Open(tempFile, FileMode.Create))
{
await streamContent.CopyToAsync(streamWrite);
}
}
Entendendo o problema
Vamos fazer essa pequena modificação:
//...
const string url = "https://ralms.io/poeira_em_alto_mar.mp4";
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
using (var streamContent = await response.Content.ReadAsStreamAsync())
{
string tempFile = Path.GetTempFileName();
using (var streamWrite = File.Open(tempFile, FileMode.Create))
{
await streamContent.CopyToAsync(streamWrite);
}
}
Resolvendo o problema
Ainda continuamos com um problema da leitura do content completamente, porque falo isso? Bom, o motivo é que se você tem pouca memória, você pode chegar ao ponto de exaurir seus recursos computacionais, então a dica é fragmentar a leitura do dado e escrever em pedaços menores em seu arquivo, isso se torna muito mais eficiente e você pode inclusive utilizar até paralelismo, veja como poderemos fazer de forma simples e resolver esse problema:
// ...
const string url = "https://ralms.io/poeira_em_alto_mar.mp4";
const int chunck = 1024 * 1024 * 5; //5Mb
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
using (var streamContent = await response.Content.ReadAsStreamAsync())
{
string tempFile = Path.GetTempFileName();
using (var streamWrite = new FileStream(tempFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, chunck, FileOptions.SequentialScan))
{
await streamContent.CopyToAsync(streamWrite, chunck); //5Mb
}
}
Observações
No exemplo acima fragmentamos em pedaços de 5Mb isso se torna mais eficiente e seguro, pricipalmente em ambientes que são containeralizados… é uma simples dica de trabalhar sobre o HTTP Client, mas que pode lhe ajudar em seu dia a dia!
Contatos
twitter: @ralmsdeveloper
linkedin: @ralmsdeveloper
Deixe um comentário