Довольно часто возникает необходимость в обмене файлами между компьютерами и телефонами, находящимися в одной локальной сети. Например, передать файл другому человеку, или себе, но на другое устройство. Дома или в офисе могут быть настроены сервисы синхронизации наподобие Дропбокса, общие папки и другие подобные средства. Но иногда может возникнуть необходимость во временном (или постоянном) средстве обмена файлами, доступном исключительно внутри сети, не ограниченном в скорости, поддерживающем крупные файлы и не требующем установки клиентских приложений. Я попробую найти решение этой задачи.
Кто эти люди на КПДВ? Это команда КВН «Союз», в одном из номеров которой прозвучала строка песни, созвучная с моей сегодняшней статьёй. А ещё это талантливые ребята, творчество которых не закончилось с окончанием карьеры в КВН.
Скрытый текст
Сначала разберёмся с возможными способами обмена файлами.
Флешки. Про дискеты, 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/
Добавить комментарий