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

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

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

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

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

Флешки. Про дискеты, 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 кодов для передачи ссылки на телефон

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

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

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

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

Комментарии (24)


  1. aik
    18.10.2024 07:17

    Я понимаю, что это курсовая какая-нибудь, но всё равно - ещё раз расскажите, почему это проще и удобнее расшареной папки? Практически любой встроенный файловый менеджер телефона знает про smb/ftp и т.п.


    1. Dinxor Автор
      18.10.2024 07:17

      Не курсовая, реально пользуюсь У нас общие папки как-то не прижились. Конкретно это решение проще тем, что не нужно устанавливать дополнительный софт на клиентов, заморачиваться с авторизацией, не создаётся файлопомойка. Удобнее наверное тем что можно пользоваться из браузера.


      1. aik
        18.10.2024 07:17

        Так и со встроенными файловыми менеджерами не надо дополнительно ничего ставить. Ну может на айфон разве что.

        На счёт же самого не надо ставить - ну так через мессенджер перекидывайте, телеграм до гигабайта бесплатно может. И сервер не нужен.

        PS. Хотя и айфон в самбу может, проверил.


        1. Dinxor Автор
          18.10.2024 07:17

          Обычно пользовался FTP, с общими папками давно уже стараюсь не связываться - со времён XP там то авторизация внезапно требовалась, то доступ слетал до перезагрузки, то ещё какие-нибудь приключения, свойственные встроенным средствам винды. В общем, дома общих папок нет, в офисе - домен со своими приколами.

          Фотки через телеграм шакалистые передаются, мне надо чтобы были в неискажённом виде. Пробовал отправить текстовый файл - "недопустимый формат". Я не хочу каждый раз выяснять, где какие ограничения и как их обойти. Я ФАЙЛ хочу отправить, не картинку, не аудиозапить, не приложение. Об этом собственно и речь.


          1. ajijiadduh
            18.10.2024 07:17

            Фотки через телеграм шакалистые передаются, мне надо чтобы были в неискажённом виде.

            а вы точно итшник? прикрепить - файл - галерея


            1. Dinxor Автор
              18.10.2024 07:17

              И всем, кто мне собрался фотку перекинуть, я должен буду инструкцию написать?


          1. aik
            18.10.2024 07:17

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

            Фотки через телеграм шакалистые передаются

            Передавайте как файл.

            "недопустимый формат"

            С этим да, бывают проблемы. Но, как правило, большинству хватает поддерживаемых стандартов.


  1. zaxisbug
    18.10.2024 07:17

    У владельцев айфонов большие проблемы с передачей файлов на кудахтер


  1. MonkAlex
    18.10.2024 07:17

    Последние годы перекидываю через телеграм

    Проще любых других решений, т.к. софт уже есть и используется на обоих устройствах

    Но в качестве запасного варианта есть мега


    1. Dinxor Автор
      18.10.2024 07:17

      Тоже часто перекидываю через телеграм. Но фотки он пережимает очень сильно. Однажды пытался перекинуть текстовый файл - "недопустимый формат". Ограничения по размеру файла. Десктоп версией не пользуюсь. Из-за всего этого и возникла идея локального файлообменника.


    1. Grey83
      18.10.2024 07:17

      Это хорошо для малых размеров файлов (меньше гига) при хорошей скорости инета.

      Для чисто локалки решение так себе (скорость низковата, т.к. по локалке скорость может быть гораздо больше, чем у инета; требуется наличие инета), хотя для мелких файлов обычно прокатывает. Мини-онлайн-файлопомойка.


      1. MonkAlex
        18.10.2024 07:17

        Соглашусь. Учитывая, что интернет есть 99.9% времени и на телефоне (мне лично) не нужны большие файлы, мои запросы покрывает.


  1. Dinxor Автор
    18.10.2024 07:17

    У нас общие папки как-то не прижились. Конкретно это решение проще тем, что не нужно устанавливать дополнительный софт на клиентов, заморачиваться с авторизацией, не создаётся файлопомойка. Удобнее наверное тем что можно пользоваться из браузера.


    1. Grey83
      18.10.2024 07:17

      Есть http-сервера сто лет как.

      Для винды я много лет (точно более 5) использовал HFS: https://www.rejetto.com/hfs/
      Можно создавать учётки и выдавать права доступа, шарить всю папку или же создавать виртуальную и помещать файлы в неё, веб-морда может даже содержать медиаплеер. В общем много чего.
      Из недостатков: отсутствие переводов интерфейса (я когда-то для себя переводил частично, но т.к. в интерфейс проги заглядываешь лишь изредка, то и переведено было менее 50% интерфейса, наверное).

      Про загрузку файлов извне не скажу: никогда не возникало такой необходимости (по локалке я файлы через самбу всегда перекидывал, что на смарт, что со смарта).


      1. Dinxor Автор
        18.10.2024 07:17

        Мне лет 15 хватало FTP для большинства задач, там было практически всё что нужно. Но есть кейсы типа Windows 7 Embedded немецкая без лишнего софта и с хитрым файрволлом, нужно с неё забрать дамп после зависания. На FTP авторизоваться можно, но грузить ничего не получается. Вот тут возможность что-то загрузить из браузера сильно пригодилась.


        1. Grey83
          18.10.2024 07:17

          ну так HFS как раз позволяет раздавать через http
          ну и у меня браузеры умеют в ftp, что на пк, что на смарте


          1. Dinxor Автор
            18.10.2024 07:17

            Глянул, неплохое решение. Но для моих задач это из пушки по воробьям, да и с node.js я не очень дружу


            1. Grey83
              18.10.2024 07:17

              Самое большое достоинство, наверное, в том что прога портабельная (и ещё умеет определять внешний IP, хотя локалке это уже не важно).

              И при чём тут нода? Все настройки делается через интерфейс самой проги.


  1. saibaneko
    18.10.2024 07:17

    1. Dinxor Автор
      18.10.2024 07:17

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


  1. Wolfdp
    18.10.2024 07:17

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


    1. Grey83
      18.10.2024 07:17

      Типа kde connect, кторому уже 11 лет?
      https://en.wikipedia.org/wiki/KDE_Connect

      Даже для винды версия есть: https://kdeconnect.kde.org/download.html


  1. Dinxor Автор
    18.10.2024 07:17

    Кстати, ссылка на ютуб с привязкой по времени почему-то открывается без этой привязки. Стал проверять.

    https://youtube.com/watch?v=_I9UwdXYEmk?t=257

    Ожидаемо обрезается второй знак вопроса в ссылке. Но такую сам ютуб выдаёт! Как так-то?

    Вот правильная ссылка:

    https://youtube.com/watch?v=_I9UwdXYEmk&t=257s

    Сейчас поправлю в статье.


  1. Habr1337
    18.10.2024 07:17

    чем плох https://localsend.org?