Как отправить файл с помощью POST-запроса в Python

Ответ

Для отправки файлов используется POST-запрос с типом содержимого multipart/form-data. Этот формат позволяет передавать бинарные данные (файл) вместе с другими текстовыми полями в одном запросе.

В Python это легко реализовать с помощью библиотеки requests.

Синхронный пример (requests):

import requests

# URL-адрес сервера, который принимает файлы
url = 'https://httpbin.org/post'

# Файл открывается в бинарном режиме для чтения ('rb')
with open('my_file.txt', 'rb') as f:
    # Словарь `files` указывает имя поля ('file') и файловый объект
    files = {'file': f}
    response = requests.post(url, files=files)

print(f"Статус-код: {response.status_code}")
print(response.json())

Ключевые моменты:

  • Файл необходимо открывать в бинарном режиме ('rb').
  • Данные передаются в параметре files в виде словаря, где ключ — это имя поля формы, а значение — файловый объект.
  • Сервер на принимающей стороне должен быть настроен на обработку multipart/form-data.

Асинхронный пример (aiohttp):

Для асинхронных приложений используется схожий подход с aiohttp.FormData.

import aiohttp
import asyncio

async def upload_file():
    async with aiohttp.ClientSession() as session:
        data = aiohttp.FormData()
        # Добавляем поле с файлом
        data.add_field('file',
                       open('my_file.txt', 'rb'),
                       filename='my_file.txt',
                       content_type='text/plain')

        async with session.post('https://httpbin.org/post', data=data) as resp:
            print(f"Статус-код: {resp.status}")
            print(await resp.json())

asyncio.run(upload_file())

Ответ 18+ 🔞

А, ну вот, смотри, классика жанра, блядь! Все эти ваши файлы, API и прочая хуйня. Слушай сюда, сейчас разжую, как бабушка кашу.

Так, значит, если тебе нужно отправить файл на сервер, то это делается через POST-запрос, но не простой, а с типом multipart/form-data. Это такая хитрая жопа, которая позволяет в одном запросе запихнуть и бинарные данные (то есть сам файл, твой любимый my_cat_meme.jpg), и обычные текстовые поля, типа "комментарий" или "описание". Всё в одной кучке, удобно, блядь.

В Питоне это проще пареной репы с помощью библиотеки requests. Смотри, как это выглядит, ёпта:

Синхронный пример (requests):

import requests

# URL-адрес сервера, который принимает файлы
url = 'https://httpbin.org/post'

# Файл открывается в бинарном режиме для чтения ('rb')
with open('my_file.txt', 'rb') as f:
    # Словарь `files` указывает имя поля ('file') и файловый объект
    files = {'file': f}
    response = requests.post(url, files=files)

print(f"Статус-код: {response.status_code}")
print(response.json())

Важные штуки, блядь, запомни:

  • Файл открывай строго в бинарном режиме ('rb'), а то получишь пиздюлей от интерпретатора.
  • Всё это добро суёшь в параметр files в виде словаря. Ключ — это имя поля на форме (обычно 'file'), а значение — сам файловый объект, который ты только что открыл.
  • И да, сервер на той стороне, куда ты это всё шлёшь, должен быть готов принимать multipart/form-data, а не жрать печеньки. Иначе будет "ошибка 400" и все дела, волнение ебать.

А если ты асинхронный пидор (шутка, я сам такой), то вот тебе пример на aiohttp:

import aiohttp
import asyncio

async def upload_file():
    async with aiohttp.ClientSession() as session:
        data = aiohttp.FormData()
        # Добавляем поле с файлом
        data.add_field('file',
                       open('my_file.txt', 'rb'),
                       filename='my_file.txt',
                       content_type='text/plain')

        async with session.post('https://httpbin.org/post', data=data) as resp:
            print(f"Статус-код: {resp.status}")
            print(await resp.json())

asyncio.run(upload_file())

Вот и вся магия, блядь. Ничего сложного, главное — не перепутай режим открытия файла, а то вместо картинки котика отправишь какую-нибудь кракозябру, и сервер тебе в ответ такое напишет, что мало не покажется.