-1

I have url where I need to download file and convert to base64 string

I wrote this code to do this

private string GetImageAsBase64(string url)
    {
        using (var client = new WebClient())
        {
            var bytes = client.DownloadData(url);
            var base64String = Convert.ToBase64String(bytes);
            return base64String;
        }
    }

How I can make it async to use returning type Task<string>?

Eugene Sukh
  • 2,357
  • 4
  • 42
  • 86
  • This is kinda similar https://stackoverflow.com/questions/13240915/converting-a-webclient-method-to-async-await – Ryan Apr 26 '21 at 10:43
  • 2
    Mind that Microsoft [discourages the use of WebClient](https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient?view=net-5.0#remarks) for new code. – Fildor Apr 26 '21 at 10:46
  • Okay, so how I can do this without `WebClient` ? @Fildor – Eugene Sukh Apr 26 '21 at 10:47
  • Use HttpClient, which has async APIs, for one. Then you can see how to make the encoding part async. – Fildor Apr 26 '21 at 10:48
  • 3
    @EugeneSukh the remark of the linked article says: "Instead, use the System.Net.Http.HttpClient class." - big and bold. you basically can't miss it if you read it. – Franz Gleichmann Apr 26 '21 at 10:48
  • ^^ In the Question Ryan linked, mind that the accepted answer is not good. Right beneath it, Stephen Cleary gave a much better one (unfortunately using `using HttpClient`, which is of yourse only good for the example and should not be used in production => see IHttpClientFactory and corresponding articles). – Fildor Apr 26 '21 at 10:54
  • try this private async System.Threading.Tasks.Task GetImageAsBase64Async(string url) { using (var client = new System.Net.WebClient()) { string data = await client.DownloadStringTaskAsync(new Uri(url)); return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(data)); } } – CooncilWorker Apr 26 '21 at 11:06
  • @CooncilWorker If you have an answer, why not write one instead of comment? – Fildor Apr 26 '21 at 11:09
  • I did not think it was worth an answer - looks like it would have been a near duplicate anyway. – CooncilWorker Apr 26 '21 at 11:29

2 Answers2

7

you are almost there, use the GetByteArrayAsync:

private async Task<string> GetImageAsBase64Async(string url) // return Task<string>
{
    using (var client = new HttpClient())
    {
        var bytes = await client.GetByteArrayAsync(url); // there are other methods if you want to get involved with stream processing etc
        var base64String = Convert.ToBase64String(bytes);
        return base64String;
    }
}

UPD

as @Fildor points out, you want to instantiate your HttpClient once and inject it into the function. A very naive way to do that would be to use an extension method:

void Main()
{
    HttpClient client = new HttpClient(); // can reuse
    client.GetImageAsBase64("...");
    client.GetImageAsBase64("...");
    client.GetImageAsBase64("...");
}

static class HttpclientExtensions
{
    public static async Task<string> GetImageAsBase64(this HttpClient client, string url)
    {
        var bytes = await client.GetByteArrayAsync(url);
        return Convert.ToBase64String(bytes);
    }
}
timur
  • 14,239
  • 2
  • 11
  • 32
  • 2
    OP: Mind that you should not be using `using (var client = new HttpClient())`. Either have a static HttpClient or use dependency injection (with [IHttpClientFactory](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests)). – Fildor Apr 26 '21 at 10:59
-2

Even if this question is already answered, as written above.

I think you need something like this:

 private async Task<string> GetImageAsBase64(string url)
    {
        using (var client = new WebClient())
        {
            var bytes = await client.DownloadDataTaskAsync(url);
            var base64String = Convert.ToBase64String(bytes);
            return base64String;
        }
    }
scharnyw
  • 2,347
  • 2
  • 18
  • 32
BigShady
  • 33
  • 8
  • As mentioned above, it better not use WebClient How I can do this, using HttpClient? – Eugene Sukh Apr 26 '21 at 10:51
  • 2
    @EugeneSukh i recommend actually reading [The Documentation](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-5.0), since it even contains _code samples_ – Franz Gleichmann Apr 26 '21 at 10:54
  • _"Even if this question is already answered, as written above."_ - The linked question is not exactly the same and on top: the highly upvoted accepted answer is _bad_ advice from today's standpoint. – Fildor Apr 26 '21 at 11:06