Como fazer o download da imagem do url

104

Existe uma maneira de baixar uma imagem diretamente de um url em c # se o url não tiver um formato de imagem no final do link? Exemplo de url:

https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-xpf1/v/t34.0-12/10555140_10201501435212873_1318258071_n.jpg?oh=97ebc03895b7acee9aebbde7d6b002bf&oe=53C9ABB0&__gda__=1405685729_110e04e71d969d392b63b27ec4f4b24a

Eu sei como baixar a imagem quando o url termina com um formato de imagem. Por exemplo:

http://img1.wikia.nocookie.net/__cb20101219155130/uncyclopedia/images/7/70/Facebooklogin.png
Ifwat Ibrahim
fonte

Respostas:

135

Simplesmente você pode usar os seguintes métodos.

using (WebClient client = new WebClient()) 
{
    client.DownloadFile(new Uri(url), @"c:\temp\image35.png");
    // OR 
    client.DownloadFileAsync(new Uri(url), @"c:\temp\image35.png");
}

Esses métodos são quase iguais a DownloadString (..) e DownloadStringAsync (...). Eles armazenam o arquivo no diretório em vez de na string C # e não precisam da extensão Format no URi

Se você não souber o formato (.png, .jpeg etc) da imagem

public void SaveImage(string filename, ImageFormat format)
{    
    WebClient client = new WebClient();
    Stream stream = client.OpenRead(imageUrl);
    Bitmap bitmap;  bitmap = new Bitmap(stream);

    if (bitmap != null)
    {
        bitmap.Save(filename, format);
    }

    stream.Flush();
    stream.Close();
    client.Dispose();
}

Usando isso

try
{
    SaveImage("--- Any Image Path ---", ImageFormat.Png)
}
catch(ExternalException)
{
    // Something is wrong with Format -- Maybe required Format is not 
    // applicable here
}
catch(ArgumentNullException)
{   
    // Something wrong with Stream
}
Charlie
fonte
4
@Arsman Ahmad é uma pergunta completamente diferente que deveria ser procurada ou feita em outro lugar. Este tópico é para o download de uma única imagem.
AzNjoE
79

Dependendo se você conhece ou não o formato da imagem, aqui estão algumas maneiras de fazer isso:

Baixar imagem para um arquivo, conhecendo o formato da imagem

using (WebClient webClient = new WebClient()) 
{
   webClient.DownloadFile("http://yoururl.com/image.png", "image.png") ; 
}

Baixe a imagem para um arquivo sem saber o formato da imagem

Você pode usar Image.FromStreampara carregar qualquer tipo de bitmaps usuais (jpg, png, bmp, gif, ...), ele irá detectar automaticamente o tipo de arquivo e você nem precisa verificar a extensão do url (o que não é muito bom prática). Por exemplo:

using (WebClient webClient = new WebClient()) 
{
    byte [] data = webClient.DownloadData("https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-xpf1/v/t34.0-12/10555140_10201501435212873_1318258071_n.jpg?oh=97ebc03895b7acee9aebbde7d6b002bf&oe=53C9ABB0&__gda__=1405685729_110e04e71d9");

   using (MemoryStream mem = new MemoryStream(data)) 
   {
       using (var yourImage = Image.FromStream(mem)) 
       { 
          // If you want it as Png
           yourImage.Save("path_to_your_file.png", ImageFormat.Png) ; 

          // If you want it as Jpeg
           yourImage.Save("path_to_your_file.jpg", ImageFormat.Jpeg) ; 
       }
   } 

}

Nota: ArgumentException pode ser lançada por Image.FromStreamse o conteúdo baixado não for um tipo de imagem conhecido.

Verifique esta referência no MSDN para encontrar todos os formatos disponíveis. Aqui estão referências a WebCliente Bitmap.

Perfect28
fonte
2
Observe que você precisa de "using System.Drawing;" para Image.FromStream ()
dlchambers
3
Observe que, em vez de pedir à biblioteca de imagens para detectar o formato da imagem, você também pode olhar os cabeçalhos de resposta para ver qual formato a fonte pensa que a imagem está usandowebClient.ResponseHeaders["Content-Type"]
bikeman868
Isso também seria muito mais eficiente em termos de memória do que expandir a imagem compactada em um objeto Bitmap descompactado e permitiria que você salve a imagem em seu formato original com sua compactação original, etc.
bikeman868
20

Para quem deseja baixar uma imagem SEM salvá-la em um arquivo:

Image DownloadImage(string fromUrl)
{
    using (System.Net.WebClient webClient = new System.Net.WebClient())
    {
        using (Stream stream = webClient.OpenRead(fromUrl))
        {
            return Image.FromStream(stream);
        }
    }
}
Brian Cryer
fonte
11

Não é necessário usar System.Drawingpara localizar o formato da imagem em um URI. System.Drawingnão está disponível para a .NET Coremenos que você baixe o pacote System.Drawing.Common NuGet e, portanto, não vejo nenhuma boa resposta entre plataformas para essa pergunta.

Além disso, meu exemplo não usa, System.Net.WebClientpois a Microsoft desestimula explicitamente o uso deSystem.Net.WebClient .

Não recomendamos que você use a WebClientclasse para novos desenvolvimentos. Em vez disso, use a classe System.Net.Http.HttpClient .

Baixe uma imagem e grave-a em um arquivo sem saber a extensão (plataforma cruzada) *

* Sem System.Net.WebCliente velho System.Drawing.

Este método irá baixar de forma assíncrona uma imagem (ou qualquer arquivo, desde que o URI tenha uma extensão de arquivo) usando o System.Net.Http.HttpCliente, em seguida, gravá-lo em um arquivo, usando a mesma extensão de arquivo que a imagem tinha no URI.

Obtendo a extensão do arquivo

A primeira parte para obter a extensão do arquivo é remover todas as partes desnecessárias do URI.
Usamos Uri.GetLeftPart () com UriPartial.Path para obter tudo, desde o Schemeaté o Path.
Em outras palavras, https://www.example.com/image.png?query&with.dotstorna-se https://www.example.com/image.png.

Depois disso, usamos Path.GetExtension () para obter apenas a extensão (em meu exemplo anterior, .png).

var uriWithoutQuery = uri.GetLeftPart(UriPartial.Path);
var fileExtension = Path.GetExtension(uriWithoutQuery);

Baixando a imagem

A partir daqui, deve ser direto. Baixe a imagem com HttpClient.GetByteArrayAsync , crie o caminho, verifique se o diretório existe e, em seguida, grave os bytes no caminho com File.WriteAllBytesAsync () (ou File.WriteAllBytesse você estiver no .NET Framework)

private async Task DownloadImageAsync(string directoryPath, string fileName, Uri uri)
{
    using var httpClient = new HttpClient();

    // Get the file extension
    var uriWithoutQuery = uri.GetLeftPart(UriPartial.Path);
    var fileExtension = Path.GetExtension(uriWithoutQuery);

    // Create file path and ensure directory exists
    var path = Path.Combine(directoryPath, $"{fileName}{fileExtension}");
    Directory.CreateDirectory(directoryPath);

    // Download the image and write to the file
    var imageBytes = await _httpClient.GetByteArrayAsync(uri);
    await File.WriteAllBytesAsync(path, imageBytes);
}

Observe que você precisa do seguinte usando diretivas.

using System;
using System.IO;
using System.Threading.Tasks;
using System.Net.Http;

Exemplo de uso

var folder = "images";
var fileName = "test";
var url = "https://cdn.discordapp.com/attachments/458291463663386646/592779619212460054/Screenshot_20190624-201411.jpg?query&with.dots";

await DownloadImageAsync(folder, fileName, new Uri(url));

Notas

  • É uma má prática criar um novo HttpClientpara cada chamada de método. Deve ser reutilizado em todo o aplicativo. Escrevi um pequeno exemplo de um ImageDownloader(50 linhas) com mais documentação que reutiliza corretamente HttpCliente elimina corretamente o que você pode encontrar aqui .
MarcusOtter
fonte
5

.net Framework permite PictureBox Control carregar imagens de url

e salvar a imagem no evento completo Laod

protected void LoadImage() {
 pictureBox1.ImageLocation = "PROXY_URL;}

void pictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e) {
   pictureBox1.Image.Save(destination); }
Ali Humayun
fonte
4

Experimente isto funcionou para mim

Escreva isso em seu controlador

public class DemoController: Controller

        public async Task<FileStreamResult> GetLogoImage(string logoimage)
        {
            string str = "" ;
            var filePath = Server.MapPath("~/App_Data/" + SubfolderName);//If subfolder exist otherwise leave.
            // DirectoryInfo dir = new DirectoryInfo(filePath);
            string[] filePaths = Directory.GetFiles(@filePath, "*.*");
            foreach (var fileTemp in filePaths)
            {
                  str= fileTemp.ToString();
            }
                return File(new MemoryStream(System.IO.File.ReadAllBytes(str)), System.Web.MimeMapping.GetMimeMapping(str), Path.GetFileName(str));
        }

Aqui está minha visão

<div><a href="/DemoController/GetLogoImage?Type=Logo" target="_blank">Download Logo</a></div>
Chandan Kumar
fonte
1

A maioria das postagens que encontrei atingirá o tempo limite após uma segunda iteração. Particularmente se você estiver percorrendo um monte de imagens como eu. Portanto, para melhorar as sugestões acima, aqui está o método completo:

public System.Drawing.Image DownloadImage(string imageUrl)
    {
        System.Drawing.Image image = null;

        try
        {
            System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(imageUrl);
            webRequest.AllowWriteStreamBuffering = true;
            webRequest.Timeout = 30000;
            webRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
            webRequest.ServicePoint.MaxIdleTime = 5000;

            using (System.Net.WebResponse webResponse = webRequest.GetResponse())
            {

                using (System.IO.Stream stream = webResponse.GetResponseStream())
                {
                    image = System.Drawing.Image.FromStream(stream);
                }
            }

            webRequest.ServicePoint.CloseConnectionGroup(webRequest.ConnectionGroupName);
            webRequest = null; 
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message, ex);

        }


        return image;
    }
Be05x5
fonte