Date:

Share:

How to download an online file and store it on file system with C# | Code4IT

Related Articles

Table of Contents

Downloading files from an online source and saving them to your local computer seems like an easy task.

And guess what? It!

In this article we will learn how to download an online file, perform some operations on it – such as checking its file extension – and store it in a local folder. We will also learn how to deal with edge cases: what if the file does not exist? Can we replace existing files?

How to download a stream of files from an online resource using HttpClient

Okay, that’s easy. If you have the URL of the file, it’s easy to just download it using HttpClient.

HttpClient httpClient = new HttpClient();
Stream fileStream = await httpClient.GetStreamAsync(fileUrl);

Through HttpClient can cause problems, especially when you have a huge computational load. As a matter of fact, through HttpClientFactory Better, as we already explained in a previous article.

But, okay, it looks easy – too easy! There are two other parts to consider.

How to handle errors when downloading a data stream

You know, shit happens!

There are at least 2 cases that prevent you from downloading a file: the file does not exist or the file requires authentication to access it.

In both cases, a HttpRequestException An exception is thrown, with the following stack trace:

at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at System.Net.Http.HttpClient.GetStreamAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)

as you can see, We communicate implicitly EnsureSuccessStatusCode while receiving the data stream.

You can tell the consumer that we were unable to download the content in two ways: throw a The custom deviation or repetition Stream.Null. we will use Stream.Null for the sake of this article.

Note: Always throw custom exceptions and add context to them: This way, you will add more useful information to consumers and logs, and you can hide application details.

So, let me recreate the part that downloads the file stream and put it in a standalone method:

async Task<Stream> GetFileStream(string fileUrl)
{
    HttpClient httpClient = new HttpClient();
    try
    {
        Stream fileStream = await httpClient.GetStreamAsync(fileUrl);
        return fileStream;
    }
    catch (Exception ex)
    {
        return Stream.Null;
    }
}

so we can use Stream.Null check the existence of the stream.

How to store a file on your local computer

Now we have our data stream. We need to store it somewhere.

We will need to copy our input stream to a FileStream An object, located within a using block.

using (FileStream outputFileStream = new FileStream(path, FileMode.Create))
{
    await fileStream.CopyToAsync(outputFileStream);
}

Possible mistakes and considerations

When creating the FileStream For example, we must also pass the full path of the image to the constructor, both with the file name and FileMode.Createwhich tells the stream what kind of operations to support.

FileMode It is a dish that comes from what System.IO namespace, and has different values. Each value is best suited for certain use cases.

public enum FileMode
{
    CreateNew = 1,
    Create,
    Open,
    OpenOrCreate,
    Truncate,
    Append
}

Again, there are some edge cases we need to consider:

  • The destination folder does not exist: You will receive DirectoryNotFoundException Outstanding. You can fix it easily by calling Directory.CreateDirectory create the entire hierarchy of folders defined in the path;
  • The target file already exists: depends on the value of FileModeYou will see different behavior. FileMode.Create replaces the image, while FileMode.CreateNew throws a IOException In case the image already exists.

Complete example

It’s time to put the pieces together:

async Task DownloadAndSave(string sourceFile, string destinationFolder, string destinationFileName)
{
    Stream fileStream = await GetFileStream(sourceFile);

    if (fileStream != Stream.Null)
    {
        await SaveStream(fileStream, destinationFolder, destinationFileName);
    }
}

async Task<Stream> GetFileStream(string fileUrl)
{
    HttpClient httpClient = new HttpClient();
    try
    {
        Stream fileStream = await httpClient.GetStreamAsync(fileUrl);
        return fileStream;
    }
    catch (Exception ex)
    {
        return Stream.Null;
    }
}

async Task SaveStream(Stream fileStream, string destinationFolder, string destinationFileName)
{
    if (!Directory.Exists(destinationFolder))
        Directory.CreateDirectory(destinationFolder);

    string path = Path.Combine(destinationFolder, destinationFileName);

    using (FileStream outputFileStream = new FileStream(path, FileMode.CreateNew))
    {
        await fileStream.CopyToAsync(outputFileStream);
    }
}

Bonus tips: How to deal with file names and extensions

You have the URL of the file, and you want to get its extension and its regular file name.

You can use several methods from Path status:

string image = "https://website.come/csharptips/format-interpolated-strings/featuredimage.png";
Path.GetExtension(image); // .png
Path.GetFileNameWithoutExtension(image); // featuredimage

But not every image has a file extension. For example, Twitter cover photos have this format: https://pbs.twimg.com/profile_banners/1164441929679065088/1668758793/1080×360

string image = "https://pbs.twimg.com/profile_banners/1164441929679065088/1668758793/1080x360";
Path.GetExtension(image); // [empty string]
Path.GetFileNameWithoutExtension(image); // 1080x360

Additional readings

As I said, you don’t need to create a instance new HttpClient() Every time. you should use HttpClientFactory Instead.

If you want to know more details, I have an article for you:

🔗 C# Tip: Use IHttpClientFactory to create HttpClient instances | Code4IT

This article first appeared on Code4IT 🐧

finishing

This was a quick article, pretty easy to understand – I hope!

My main point here is that not everything is always as easy as it seems – you should always consider edge cases!

I hope you enjoyed this article! Let’s keep in touch Twitter or on LinkedIn, If you want! 🤜🤛

Happy coding!

🐧

.

Source

Popular Articles