No es necesario utilizar System.Drawing
para buscar el formato de imagen en un URI. System.Drawing
no está disponible a .NET Core
menos 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.WebClient
ya que Microsoft desalienta explícitamente el uso deSystem.Net.WebClient
.
No recomendamos que use la WebClient
clase 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.WebClient
y 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.HttpClient
y 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 Scheme
hasta el Path
.
En otras palabras, se https://www.example.com/image.png?query&with.dots
convierte 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.WriteAllBytes
si 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
HttpClient
para 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 HttpClient
y lo desecha correctamente que puede encontrar aquí .