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í .