Creating a file downloader with user input


I wrote this code to download a file from a given URL and display the download progress in terms of bytes and percentage. I explain briefly what each component does.

First, I imported the necessary modules: time for measuring execution time, urllib.request for downloading files, urlparse from urllib.parse for parsing URLs, and os for working with file paths.

a. I defined a class called download_file, which has an __init__ method and a get_file method. The __init__ method is empty because it doesn't need any initialisation logic.

b. The get_file method takes a link parameter, which represents the URL of the file to be downloaded. Inside the method, I tried to download the file using the provided link.

c. To start, I extracted the filename and extension from the link using the get_extension method. Then, I printed the filename to indicate which file I'm attempting to download.

d. Next, I used urllib.request.urlopen to open the URL and obtain a response object. From the response, I extracted the total file size using the Content-Length header.

e. I initialised variables for tracking the downloaded size and set them to zero. Then, I opened a file in binary mode using the extracted filename and a with statement to ensure proper handling and closing of the file.

f. I printed the total file size to give the user an idea of the overall size. Inside a while loop, I read the file in chunks of 1024 bytes using get.read(1024).

g. If there is no more data to read, I break out of the loop. Otherwise, I update the downloaded size and write the buffer to the file. I also calculate the download progress percentage.

h. To display the progress, I printed the number of bytes downloaded and the progress percentage using the format method. The end='\r' parameter allows me to overwrite the previous line, making the progress update appear on a single line.

i. Once the loop finishes, I print a message indicating that the download is complete.

j. The get_extension method extracts the filename and extension from the provided link. I use urlparse to parse the link and extract the filename using os.path.basename. The extension is obtained using os.path.splitext.

k. In the main function, I prompt the user to enter a file link and start recording the execution time. I create an instance of the download_file class, call its get_file method to initiate the download, and then record the end time.

l. Finally, I calculate and print the total execution time by subtracting the start time from the end time.

Remember, the main function won't be called if the script is imported. It needs to be directly executed. Below is a sample input and output of the program. I simply entered 'https://www.wordpress.org/latest.zip' when prompted.

Enter a link to a file to download: https://www.wordpress.org/latest.zip
Attempting to download file: latest.zip
Total file size: 24498824.00 bytes
Downloaded: 24498824 bytes 100.00%
Download complete!
Time taken to download: 4.431303 seconds

Complete Code


import time  # Import the time module for measuring the execution time
import urllib.request  # Import the urllib.request module for downloading files
from urllib.parse import urlparse  # Import the urlparse function from urllib.parse for parsing URLs
import os  # Import the os module for working with file paths

class download_file:
    def __init__(self):
        pass

    def get_file(self, link):
        try:
            self.filename = self.get_extension(link)  # Get the filename and extension from the link
            print("Attempting to download file: " + self.filename[0])  # Print the filename
            get = urllib.request.urlopen(link)  # Open the URL to download the file
            total_size = int(get.headers['Content-Length'])  # Get the total size of the file
            downloaded_size = 0  # Initialize the downloaded size counter

            with open(self.filename[0], "wb") as file:  # Open the file for writing in binary mode
                print("Total file size: {:.2f} bytes".format(total_size))  # Print the total file size
                while True:
                    buffer = get.read(1024)  # Read a chunk of data (1024 bytes) from the URL
                    if not buffer:  # If no more data is read, break the loop
                        break
                    downloaded_size += len(buffer)  # Increment the downloaded size counter
                    file.write(buffer)  # Write the data to the file
                    percent = downloaded_size * 100 / total_size  # Calculate the download progress percentage
                    print("Downloaded: {} bytes {:.2f}%".format(downloaded_size, percent), end='\r')  # Print the download progress

            print("\nDownload complete!")  # Print a message indicating that the download is complete
        except Exception as err:  # Catch any exceptions that occur during the download process
            print("Error downloading: " + str(err))  # Print the error message

    def get_extension(self, link):
        parsed_link = urlparse(link)  # Parse the link to extract the filename and extension
        filename = os.path.basename(parsed_link.path)  # Extract the filename from the parsed link
        extension = os.path.splitext(filename)[1]  # Extract the extension from the filename
        return filename, extension  # Return the filename and extension as a tuple

def main():
    file_to_download = input("Enter a link to a file to download: ")  # Prompt the user to enter a file link
    start = time.time()  # Record the current time
    download = download_file()  # Create an instance of the download_file class
    download.get_file(file_to_download)  # Call the get_file method to download the file
    end = time.time()  # Record the current time
    print("Time taken to download: {:.6f} seconds".format(end - start))  # Print the total execution time

if __name__ == '__main__':
    main()  # Call the main function if the script is executed directly

Enquiries

[email protected]

Copyright © 2023 - slash-root.com