Отправка файлов

Последнее обновление: 09.12.2025

Одной из распространенных задач веб-приложений и веб-серверов является отправка файлов. При создании http-сервера на основе HTTPServer для обработки файлов (их открытия и считывания) мы можем использовать встроенные возможности Python, в частности, функцию open()

Для обработки файлов в http-сервере определим следующий скрипт:

from http.server import HTTPServer, BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        
        # Для других запросов убираем слеш в начале (например, "/content.txt" -> "content.txt")
        path_to_file = self.path.lstrip("/")

        try:
            # ПЫТАЕМСЯ открыть файл в режиме чтения БАЙТОВ (rb - read binary)
            # Режим "rb" позволяет отдавать не только текст,  но и картинки, PDF и т.д.
            with open(path_to_file, "rb") as file:
                content = file.read()
            
            # Если файл открылся успешно, отправляем 200 OK
            self.send_response(200)
            
            # Определяем тип контента (упрощенно)
            if path_to_file.endswith(".txt"):
                self.send_header("Content-type", "text/plain; charset=utf-8")
            elif path_to_file.endswith(".jpg"):
                self.send_header("Content-type", "image/jpeg")
            else:
                self.send_header("Content-type", "application/octet-stream")
                
            self.end_headers()
            
            # Записываем прочитанные байты файла в ответ
            self.wfile.write(content)

        except FileNotFoundError:
            # Если файл не найден на диске, возвращаем ошибку 404
            self.send_error(404, "File Not Found")


# Настройки запуска
hostName = "localhost"
serverPort = 8000

# Инициализация сервера
webServer = HTTPServer((hostName, serverPort), MyHandler)
print(f"Сервер запущен: http://{hostName}:{serverPort}")

# Бесконечный цикл прослушивания порта
try: webServer.serve_forever()
except KeyboardInterrupt: pass

webServer.server_close()
print("Сервер остановлен...")

Для отправки файлов в методе do_GET() класса MyHandler прежде всего получаем путь к файлу:

path_to_file = self.path.lstrip("/")

В данном случае мы предполагаем, что пользователь будет обращаться в браузере по адресу "http://localhost:8000/content.txt", где последняя часть адреса - "content.txt" представляет имя файла, который мы хотим отправить пользователю. Также предполагаем, что файлы будут располагаться в текущей папке.

Далее в конструкции try..except считываем и отправляем запрошенный файл. И здесь надо выделить следующие моменты:

  1. open(path_to_file, "rb")

    Мы используем режим "rb" (read binary), что позволяет считать файл как набор байтов, тем более HTTP-сервер работает с байтами. Чтение в бинарном режиме позволит считывать любой файл.

  2. Смотрим на расширение файла, и зависимости от этого расширения устанавливаем соответствующий тип ответа:

    if path_to_file.endswith(".txt"):
        self.send_header("Content-type", "text/plain; charset=utf-8")
    elif path_to_file.endswith(".jpg"):
        self.send_header("Content-type", "image/jpeg")
    else:
        self.send_header("Content-type", "application/octet-stream")
    

    Это позволит клиенту (браузеру) должным образом обрабатывать полученный файл

  3. Обработка ошибок try...except FileNotFoundError

    Если пользователь запросит несуществующий файл, и скрипт попытается его открыть, то без блока try/except сервер упадет с ошибкой и выключится. С блоком с помощью метода self.send_error() он корректно вернет стандартную страницу 404.

    except FileNotFoundError:
        self.send_error(404, "File Not Found")
    

Протестируем функциональность. Определим в папке сервера несколько файлов.

eugene@Eugene:~/python/httpserver$ ls -l
total 1853
-rwxrwxrwx 1 root root    2180 Dec  8 20:46 app.py
-rwxrwxrwx 1 root root     140 Aug 17 11:55 hello.txt
-rwxrwxrwx 1 root root 1888236 Feb 25  2013 winter.jpg
eugene@Eugene:~/python/httpserver$ 

Обратимся к файлам. Например, у меня в папке есть файл изображения "winter.jpg":

HTTP-сервер на Python с помощью класса HTTPServer и отправка файлов

Однако сразу стоит отметить вопросы безопасности. В данном случае представлен упрощенный пример, но надо учитывать, что мы, например, можем обратиться по адресу "http://localhost:8000/./secrets.txt". В этом случае локальным путем к файлу будет относительный путь "./secrets.txt", который предполагает, что есть файл "secrets.txt", который располагается в родительской папке (каталог на уровень выше). И если такой файл имеется, Python успешно его считает и отправит пользователю.

SimpleHTTPRequestHandler

Если не нужно обрабатывать данные вручную, а нужно только отдавать файлы (как обычный веб-сервер типа Nginx или Apache), в модуле http.server есть класс SimpleHTTPRequestHandler. ПРичем в этом случае нам даже не нужно писать метод do_GET() и какую-то логику обработки - вся необходимая логика уже встроена в SimpleHTTPRequestHandler, который умеет автоматически находить файлы в папке, определять их тип (MIME-type) и отдавать их. Он также сам ищет index.html, если запрошен корень.

:

from http.server import HTTPServer, SimpleHTTPRequestHandler

# Настройки запуска
hostName = "localhost"
serverPort = 8000

# Инициализация сервера
webServer = HTTPServer((hostName, serverPort), SimpleHTTPRequestHandler)
print(f"Сервер запущен: http://{hostName}:{serverPort}")

# Бесконечный цикл прослушивания порта
try: webServer.serve_forever()
except KeyboardInterrupt: pass

webServer.server_close()
print("Сервер остановлен...")

Например, обратимся к текущему файлу скрипта

HTTP-сервер на Python с помощью класса HTTPServer и отправка файлов с SimpleHTTPRequestHandler

В данном случае мы видим, что файл с расширением .py (скрипт Python) автоматически определяется как текстовый. При ручной отправке файла нам пришлось бы определять сооветствующую логику, а SimpleHTTPRequestHandler все делает автоматически. Тем не менее по скриншоту видно, что у нас могут возникнуть проблемы с кодировкой (поддержкой кириллицы).

Помощь сайту
Юмани:
410011174743222
Номер карты:
4048415020898850