URLから画像をダウンロードする方法


103

リンクの末尾にURLの画像形式がない場合、C#の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

回答:


134

単に 次の方法を使用できます。

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#文字列ではなくDirectoryに保存され、URiでFormat拡張子を付ける必要はありません。

画像のフォーマット(.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 2017

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

}

注:Image.FromStreamダウンロードされたコンテンツが既知の画像タイプでない場合、ArgumentExceptionがスローされることがあります。

利用可能なすべての形式を見つけるには、MSDNでこのリファレンスを確認してください。WebClientとへの参照Bitmapです。


2
「System.Drawingを使用する」が必要であることに注意してください。Image.FromStream()の場合
dlchambers 2016年

3
代わりに、あなたはまた、応答ヘッダを見ることができる画像フォーマットを検出するイメージングライブラリを尋ねるのソースは画像を使用していると考えてどのような形式を確認することに注意webClient.ResponseHeaders["Content-Type"]
bikeman868

また、これは、非圧縮のビットマップオブジェクトに圧縮された画像を拡大するよりもはるかに多くのメモリ効率的である、とあなたは、元の圧縮を元の形式で画像等を保存することができるようになる
bikeman868

19

ファイルに保存せずに画像をダウンロードしたい人のために:

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

9

System.DrawingURIで画像形式を見つけるためにを使用する必要はありません。System.Drawing.Common NuGetパッケージをダウンロードSystem.Drawing.NET Coreない限り、は利用できません。そのため、この質問に対する適切なクロスプラットフォームの回答はありません。

また、Microsoftはの使用を明示的に推奨していないため、私の例では使用しSystem.Net.WebClientていません。System.Net.WebClient

WebClient新規開発のためにクラスを使用することはお勧めしません。代わりに、System.Net.Http.HttpClientクラスを使用します。

拡張子を知らずに画像をダウンロードしてファイルに書き込む(クロスプラットフォーム)*

*古いものSystem.Net.WebClientとなしSystem.Drawing

このメソッドは、を使用して画像(またはURIにファイル拡張子がある限り任意のファイル)を非同期でダウンロードし、URIにあるSystem.Net.Http.HttpClient画像と同じファイル拡張子を使用してファイルに書き込みます。

ファイル拡張子の取得

ファイル拡張子を取得する最初の部分は、URIからすべての不要な部分を削除することです。UriPartial.PathでUri.GetLeftPart()
を使用して、からまでのすべてを取得します。 つまり、になります。SchemePath
https://www.example.com/image.png?query&with.dotshttps://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、適切に廃棄するためのドキュメントがここにあります

5

.netフレームワークにより、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

私が見つけた投稿のほとんどは、2回目の反復後にタイムアウトになります。特にあなたが私がそうであるように画像の場合、束をループしている場合。したがって、上記の提案を改善するには、ここにメソッド全体があります。

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;
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.