Как скачать изображение с url

106

Есть ли способ загрузить изображение прямо с URL-адреса в С #, если URL-адрес не имеет формата изображения в конце ссылки? Пример 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

Я знаю, как загрузить изображение, если URL-адрес заканчивается форматом изображения. Например:

http://img1.wikia.nocookie.net/__cb20101219155130/uncyclopedia/images/7/70/Facebooklogin.png
Ифват Ибрагим
источник

Ответы:

137

Просто вы можете использовать следующие методы.

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

Эти методы почти такие же, как DownloadString (..) и DownloadStringAsync (...). Они хранят файл в каталоге, а не в строке C # и не нуждаются в расширении формата в URi.

Если вы не знаете формат изображения (.png, .jpeg и т. Д.)

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

Используй это

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
}
Чарли
источник
4
@Arsman Ahmad, это совершенно другой вопрос, который нужно искать или задавать в другом месте. Эта ветка предназначена для загрузки одного изображения.
AzNjoE
79

В зависимости от того, знаете ли вы формат изображения или нет, это можно сделать следующими способами:

Загрузите изображение в файл, зная формат изображения

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

Загрузить изображение в файл, не зная формата изображения

Вы можете использовать Image.FromStreamдля загрузки любых обычных растровых изображений (jpg, png, bmp, gif, ...), он автоматически определит тип файла, и вам даже не нужно проверять расширение url (что не очень хорошо практика). Например:

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

}

Примечание. ArgumentException может быть вызвано, Image.FromStreamесли загруженное содержимое не является известным типом изображения.

Проверьте эту ссылку на MSDN, чтобы найти все доступные форматы. Вот ссылки на WebClientи Bitmap.

Идеально28
источник
2
Обратите внимание, что вам нужно "using System.Drawing;" для Image.FromStream ()
dlchambers
3
Обратите внимание, что вместо того, чтобы запрашивать библиотеку изображений для определения формата изображения, вы также можете посмотреть заголовки ответов, чтобы узнать, какой формат, по мнению источника, использует изображениеwebClient.ResponseHeaders["Content-Type"]
bikeman868
Это также будет намного более эффективно с точки зрения памяти, чем расширение сжатого изображения в несжатый объект Bitmap, и позволит вам сохранить изображение в его исходном формате с исходным сжатием и т. Д.
bikeman868
20

Для тех, кто хочет скачать изображение БЕЗ сохранения в файл:

Image DownloadImage(string fromUrl)
{
    using (System.Net.WebClient webClient = new System.Net.WebClient())
    {
        using (Stream stream = webClient.OpenRead(fromUrl))
        {
            return Image.FromStream(stream);
        }
    }
}
Брайан Крайер
источник
11

Необязательно использовать System.Drawingдля поиска формата изображения в URI. System.Drawingнедоступен, .NET Coreесли вы не загрузите пакет NuGet System.Drawing.Common, и поэтому я не вижу хороших кросс-платформенных ответов на этот вопрос.

Кроме того, мой пример не используется, System.Net.WebClientпоскольку Microsoft явно не рекомендует использоватьSystem.Net.WebClient .

Мы не рекомендуем использовать этот WebClientкласс для новых разработок. Вместо этого используйте класс System.Net.Http.HttpClient .

Загрузите изображение и запишите его в файл, не зная расширения (кроссплатформенность) *

* Без старых System.Net.WebClientи System.Drawing.

Этот метод будет асинхронно загружать изображение (или любой файл, если URI имеет расширение файла) с помощью, System.Net.Http.HttpClientа затем записывает его в файл, используя то же расширение файла, что и у изображения в URI.

Получение расширения файла

Первая часть получения расширения файла - это удаление всех ненужных частей из URI.
Мы используем Uri.GetLeftPart () с UriPartial.Path , чтобы получить все от Schemeдо к Path.
Другими словами, https://www.example.com/image.png?query&with.dotsстановится https://www.example.com/image.png.

После этого мы используем Path.GetExtension (), чтобы получить только расширение (в моем предыдущем примере .png).

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

Скачивание образа

Отсюда все должно быть прямо. Загрузите изображение с помощью HttpClient.GetByteArrayAsync , создайте путь, убедитесь, что каталог существует, а затем запишите байты в путь с помощью File.WriteAllBytesAsync () (или File.WriteAllBytesесли вы используете .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);
}

Обратите внимание, что вам потребуются следующие директивы using.

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

Пример использования

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

Ноты

  • Плохая практика - создавать новый HttpClientдля каждого вызова метода. Предполагается, что он будет повторно использован во всем приложении. Я написал короткий пример ImageDownloader(50 строк) с дополнительной документацией, которая правильно повторно использует HttpClientи правильно избавляется от нее, которую вы можете найти здесь .
MarcusOtter
источник
5

.net Framework позволяет элементу управления PictureBox загружать изображения с URL-адреса

и сохранить изображение в Laod Complete Event

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

void pictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e) {
   pictureBox1.Image.Save(destination); }
Али Хумаюн
источник
4

Попробуй, это сработало для меня

Напишите это в своем контроллере

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

Вот мой взгляд

<div><a href="/DemoController/GetLogoImage?Type=Logo" target="_blank">Download Logo</a></div>
Чандан Кумар
источник
1

Большинство сообщений, которые я нашел, будут отключены после второй итерации. В частности, если вы просматриваете кучу изображений, как я. Итак, чтобы улучшить предложения выше, вот весь метод:

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
источник