Python & aiohttp: How to upload files to a remote server

Updated: August 25, 2023 By: Khue Post a comment

aiohttp is a library that provides asynchronous HTTP client and server functionality for Python. It allows you to use the async/await syntax and perform concurrent requests without blocking the main thread of your program.

In order to upload files to a remote server, you need to use the aiohttp.ClientSession class, which provides a high-level interface for making HTTP requests. You also need the help of the aiohttp.FormData class, which allows you to create a multipart/form-data body for your request. Let’s examine a practical example for a better and deeper understanding.

Example

In this example, we’ll upload some photos to the following API endpoint:

https://api.slingacademy.com/v1/sample-data/photos

The Steps

1. Install the aiohttp package by running:

pip install aiohttp

2.  Import the aiohttp module and create an instance of the aiohttp.ClientSession class (a session object). You can use the async with statement to ensure that the session is closed when you are done with it.

3. Next, you need to create an instance of the aiohttp.FormData class and add the file that you want to upload. You can use the add_field() method to specify the name, value, filename, and content type of the file.

4. Call the post() method on the session object to send a POST request to the server URL with the form data as the data argument. You can also specify headers if your server requires by using the headers argument (such as an authentication token).

5. Do something with the response and handle errors that may occur during the request or response processing.

Complete Code

Below is the final code that implements the steps we’ve discussed above. Before running it, put a photo named photo.jpeg or photo.png in the same directory as your Python script.

# SlingAcademy.com
# This example uses Python 3.11.4

import asyncio
import aiohttp
import os


async def upload_files(file_path, server_url):
    # Create a session object
    async with aiohttp.ClientSession() as session:
        # Create a form data object
        data = aiohttp.FormData()

        # Get the filename and extension of the file
        filename = os.path.basename(file_path)
        extension = os.path.splitext(file_path)[1]
        # Get the content type based on the extension
        if extension == ".jpg" or extension == ".jpeg":
            content_type = "image/jpeg"
        elif extension == ".png":
            content_type = "image/png"
        else:
            content_type = "application/octet-stream"

        # Add the file to the form data
        data.add_field(
            name="file",
            value=open(file_path, "rb"),
            filename=filename,
            content_type=content_type,
        )

        # Send a POST request to the server URL with the form data
        async with session.post(
            server_url,
            data=data,
            headers={"Authorization": "Bearer 123456"},  # Specify headers if necessary
            ssl=False,
        ) as response:
            # Get the status code, headers, and body of the response
            status = response.status
            body = await response.json()
            # Print the response information
            print(f"Status: {status}")
            print(f"Body: {body}")

            # Handle errors or exceptions if any
            if status != 200 and status != 201:
                print(f"Error: {response.reason}")


# Try it out
server_url = "https://api.slingacademy.com/v1/sample-data/photos"
file_path = 'photo.jpeg'

asyncio.run(upload_files(file_path, server_url))

Output:

Status: 201
Body: {'success': True, 'message': 'File uploaded successfully', 'file_name': 'photo.jpeg', 'file_size': '32.71 kilobytes', 'file_type': 'image/jpeg', 'created_at': '2023-08-25 08:23:09.612714+00:00 GMT'}

The status code 201 means that the request has succeeded and has led to the creation of a new resource on the server.

Conclusion

You’ve learned how to asynchronously upload files to a remote server by using aiohttp. This is an efficient and go-to approach you should go with in modern Python projects. Happy coding & have a nice day!