Жаль, что мы не умеем обмениваться файлами

от автора

Довольно часто возникает необходимость в обмене файлами между компьютерами и телефонами, находящимися в одной локальной сети. Например, передать файл другому человеку, или себе, но на другое устройство. Дома или в офисе могут быть настроены сервисы синхронизации наподобие Дропбокса, общие папки и другие подобные средства. Но иногда может возникнуть необходимость во временном (или постоянном) средстве обмена файлами, доступном исключительно внутри сети, не ограниченном в скорости, поддерживающем крупные файлы и не требующем установки клиентских приложений. Я попробую найти решение этой задачи.

Изображение из открытых источников

Изображение из открытых источников

Кто эти люди на КПДВ? Это команда КВН «Союз», в одном из номеров которой прозвучала строка песни, созвучная с моей сегодняшней статьёй. А ещё это талантливые ребята, творчество которых не закончилось с окончанием карьеры в КВН.

Скрытый текст

Сначала разберёмся с возможными способами обмена файлами.

Флешки. Про дискеты, CD и внешние диски вспоминать не будем — суть та же, но эпоха уже другая. Их никогда нет под рукой в нужный момент, USB разъёмы заняты/плохо работают/в офисе отключены админами. Скорость страдает — файлы нужно сначала записать (очистив под них место), затем прочитать. Да и как-то стыдно заниматься подобным при наличии сети.

Общие папки Windows. Какая шикарная была возможность! За исключением того, что разные версии системы плохо между собой соединялись (впрочем, одинаковые иногда тоже), а расшаренная папка довольно быстро превращалась в неорганизованную файлопомойку, которую мог внезапно заразить какой-нибудь вирус. В основном пропала с ужесточением прав доступа и переходом на новую версию протокола, да и на телефонах это не работает.

FTP. Сервер нужно устанавливать, можно запустить временный (например Babyftp). Клиенты доступны для всех платформ, в старых версиях Windows был встроенный консольный клиент. Сейчас поддержку этого протокола убрали из браузеров. Мне доводилось сталкиваться с хитро настроенными файрволлами, которые установить соединение позволяли, а пропускать файлы отказывались. Ещё из интересных случаев — работающий уже 15 лет FTP сервер внезапно ушёл в оффлайн. Оказалось, что доблестный защитник Windows определил его как возможно, вирус и отправил в карантин, сорвав плановое копирование бэкапов.

Электронная почта. Тут с телефонами наоборот всё гораздо проще. Недостаток — файлы уходят наружу и как следствие время передачи по сети удваивается. Ещё есть вопросы с безопасностью, также крупные файлы не помещаются в ящик — придётся загружать в облако или на файлообменник. Обменники могут порадовать нескучной капчей и показать кучу рекламы, а облака требуют авторизации, и место там иногда внезапно заканчивается.

Мессенджеры — на мой взгляд, чемпионы по неумению обмениваться файлами. Они откажутся передавать файл из-за большого размера (целых 30 мегабайт!) или неподдерживаемого типа (чем TXT не угодил?) и пережмут до неузнаваемости фотографии. Те же проблемы с передачей наружу, ещё использование десктоп и веб-версий не всегда уместно.

В общем, рассматриваю кейс: компьютеры и телефоны в локальной сети. Браузер есть везде, поэтому логично использовать его. Необходим сервер, способный принимать и отдавать файлы достаточно большого объёма (гигабайты), с возможностью формирования коротких ссылок и/или кодов для скачивания. От концепции файлопомойки хотелось бы уйти: возможности просматривать список файлов не будет, для скачивания нужны ссылка или код. Получается файлообменник, только локальный и без рекламы. Отдельно уточню про имена файлов: русскоязычные имена поддерживаться должны, но без фанатизма: эмодзи, иероглифы и спецсимволы скорее всего нет.

Язык для реализации проекта — Python, в качестве веб-сервера буду использовать FastAPI. Он асинхронный и умеет передавать файлы частями, не загружая в память целиком. Хранить имена файлов и сгенерированные коды буду в базе данных SQLite, для небольшого сервиса её вполне достаточно. Тем более что чтение будет производиться только при запуске, а запись при добавлении файлов. Для работы с базой использую асинхронную библиотеку aiosqlite.

Страница загрузки и скачивания файла

Страница загрузки и скачивания файла

Алгоритм работы такой: пользователь на странице отправки выбирает файл и нажимает кнопку «Загрузить», файл отправляется на сервер и сохраняется в папку, имя которой генерируется в виде случайного 5-значного числа. Это число является кодом для скачивания, оно вместе с именем файла записывается в базу данных. После этого файл доступен для скачивания по ссылке, содержащей этот код, или на странице с полем ввода кода.

Код и ссылка для скачивания загруженного файла

Код и ссылка для скачивания загруженного файла
Скрытый текст
@app.get("/") @app.get('/fo', response_class=HTMLResponse) async def fo_page(file: str = Query(default="")):     if file:         fileid = int(file)         filename = files.get(fileid, '')         if filename:             return FileResponse(path=f'files/{fileid}/{filename}', filename=filename)         else:             return HTMLResponse(nof_page)     else:         return HTMLResponse(u_page)   @app.post("/fo") async def upload(file: UploadFile = File(...)):     if file.filename:         fileid = randint(10000, 99999)         while fileid in files.keys():             fileid = randint(10000, 99999)         save_dir = f'files\\{fileid}'         if not os.path.exists(save_dir):             os.makedirs(save_dir)         try:             async with aiofiles.open(f'{save_dir}\\{file.filename}', 'wb') as f:                 while contents := file.file.read(1024 * 1024):                     await f.write(contents)         except Exception:             return {"message": "There was an error uploading the file"}         finally:             file.file.close()             files.update({fileid: file.filename})             await db.add_file_to_table(file.filename, fileid)         return HTMLResponse(done_page.format(fileid = fileid, filename = file.filename))     else:         return HTMLResponse(u_page) 

Веб-сервер уместился в 50 строк кода (не считая шаблонов страниц), реализация работы с БД примерно столько же. Но сервис получился реально удобный. Файл размером 4 Гб загрузился и скачался без проблем на полной скорости сети. Возможны дальнейшие пути развития:

  • Добавить автоудаление файлов по таймеру или после определённого количества скачиваний

  • Генератор QR кодов для передачи ссылки на телефон

  • Логгирование, админка с возможностью просматривать и чистить список файлов

  • «Золотые» короткие ссылки на наиболее востребованные файлы

  • Телеграм бот для приёма и отправки файлов извне локальной сети

Полный код доступен по ссылке.


ссылка на оригинал статьи https://habr.com/ru/articles/851558/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *