Cómo descargar la imagen de la url

103

¿Hay alguna manera de descargar una imagen directamente desde una URL en c # si la URL no tiene un formato de imagen al final del enlace? Ejemplo 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

Sé cómo descargar la imagen cuando la URL termina con un formato de imagen. P.ej:

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

Respuestas:

134

Simplemente puede utilizar los siguientes 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");
}

Estos métodos son casi los mismos que los de DownloadString (..) y DownloadStringAsync (...). Almacenan el archivo en el directorio en lugar de en la cadena C # y no necesitan la extensión de formato en URi

Si no conoce el formato (.png, .jpeg, etc.) de la imagen

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();
}

Usándolo

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
fuente
4
@Arsman Ahmad esa es una pregunta completamente diferente que debería buscarse o hacerse en otro lugar. Este hilo es para descargar una sola imagen.
AzNjoE
79

Dependiendo de si conoce o no el formato de la imagen, aquí hay formas de hacerlo:

Descargar imagen a un archivo, conociendo el formato de imagen

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

Descargar la imagen a un archivo sin conocer el formato de la imagen

Puede usar Image.FromStreampara cargar cualquier tipo de mapa de bits habitual (jpg, png, bmp, gif, ...), detectará automáticamente el tipo de archivo y ni siquiera necesita verificar la extensión de la URL (que no es muy buena práctica). P.ej:

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 puede aparecer Image.FromStreamsi el contenido descargado no es un tipo de imagen conocido.

Consulte esta referencia en MSDN para encontrar todos los formatos disponibles. Aquí se hace referencia a WebClienty Bitmap.

Perfecto28
fuente
2
Tenga en cuenta que necesita "utilizar System.Drawing;" para Image.FromStream ()
dlchambers
3
Tenga en cuenta que en lugar de pedirle a la biblioteca de imágenes que detecte el formato de imagen, también puede mirar los encabezados de respuesta para ver qué formato cree la fuente que está usando la imagenwebClient.ResponseHeaders["Content-Type"]
bikeman868
Esto también sería mucho más eficiente en memoria que expandir la imagen comprimida en un objeto de mapa de bits sin comprimir, y le permitiría guardar la imagen en su formato original con su compresión original, etc.
bikeman868
19

Para cualquiera que quiera descargar una imagen SIN guardarla en un archivo:

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
fuente
10

No es necesario utilizar System.Drawingpara buscar el formato de imagen en un URI. System.Drawingno está disponible a .NET Coremenos que descargue el paquete System.Drawing.Common NuGet y, por lo tanto, no veo ninguna buena respuesta multiplataforma a esta pregunta.

Además, mi ejemplo no se usa System.Net.WebClientya que Microsoft desalienta explícitamente el uso deSystem.Net.WebClient .

No recomendamos que use la WebClientclase para nuevos desarrollos. En su lugar, use la clase System.Net.Http.HttpClient .

Descarga una imagen y escríbela en un archivo sin conocer la extensión (multiplataforma) *

* Sin edad System.Net.WebClienty System.Drawing.

Este método descargará de forma asincrónica una imagen (o cualquier archivo siempre que el URI tenga una extensión de archivo) usando el System.Net.Http.HttpClienty luego lo escribirá en un archivo, usando la misma extensión de archivo que tenía la imagen en el URI.

Obtener la extensión del archivo

La primera parte para obtener la extensión del archivo es eliminar todas las partes innecesarias del URI.
Usamos Uri.GetLeftPart () con UriPartial.Path para obtener todo, desde el Schemehasta el Path.
En otras palabras, se https://www.example.com/image.png?query&with.dotsconvierte en https://www.example.com/image.png.

Después de eso, usamos Path.GetExtension () para obtener solo la extensión (en mi ejemplo anterior, .png).

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

Descargando la imagen

A partir de aquí debería ser sencillo. Descargue la imagen con HttpClient.GetByteArrayAsync , cree la ruta, asegúrese de que el directorio exista y luego escriba los bytes en la ruta con File.WriteAllBytesAsync () (o File.WriteAllBytessi está en .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);
}

Tenga en cuenta que necesita las siguientes directivas using.

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

Uso de ejemplo

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

  • Es una mala práctica crear una nueva HttpClientpara cada llamada de método. Se supone que debe reutilizarse en toda la aplicación. Escribí un breve ejemplo de un ImageDownloader(50 líneas) con más documentación que reutiliza correctamente HttpClienty lo desecha correctamente que puede encontrar aquí .
Marcus Nutria
fuente
5

.net Framework permite PictureBox Control cargar imágenes desde la URL

y guardar imagen en evento completo de Laod

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

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

Prueba esto, funcionó para mí

Escribe esto en tu 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));
        }

Esta es mi vista

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

La mayoría de las publicaciones que encontré expirarán después de una segunda iteración. Particularmente si estás recorriendo un montón de imágenes como yo. Entonces, para mejorar las sugerencias anteriores, aquí está el 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
fuente