Обработка файлов, загружаемых в чат

Сервис Webim позволяет пользователям и операторам обмениваться различными файлами с помощью чата. В этом материале описаны ограничения, связанные с передачей файлов, а также схемы прохождения трафика при работе с файлами.

В статье используется понятие Webim Server. Это серверное программное обеспечение сервиса Webim (бекэнд). Оно может быть установлено либо на серверах сервиса Webim, либо на серверах заказчика.

Ограничения отправки файлов в чат

Ограничения, связанные с обменом файлами в чате, регламентируются системными настройками, которые указываются в специальном табличном редакторе настроек аккаунта (account config), которые размещаются по отдельному URL-адресу. Если у Вас есть к нему доступ, Вы можете редактировать настройки самостоятельно, в противном случае попросите об этом техническую поддержку Webim.

В первую очередь стоит упомянуть настройки, которые по умолчанию разрешают и оператору, и посетителю слать файлы в чат:

  • visitor_upload_file определяет, могут ли посетители отправлять файлы в чат. По умолчанию true.
  • operator_file_upload_disable определяет, не запрещено ли оператору отправлять файлы в чат. По умолчанию установлено значение false (не запрещено).

Также ограничивать можно типы файлов, отправляемых посетителями и ботами, допустимые размеры файлов. При этом оператор из РМО сможет отправлять типы файлов, которые не могут отправлять посетители. В случае с каналами общения корректность доставки и отображения файлов, отправленных оператором, в том или ином канале общения зависит от особенностей конкретного канала.

Ограничения по типам файлов

  • allowed_upload_file_types — задаёт список расширений файлов, которые посетителю разрешается отправлять (белый список). По умолчанию указаны следующие типы файлов: png, jpg, jpeg, doc, rtf, gif, txt, pdf, docx, webp, oga, ogg.
  • allowed_upload_file_content_types — задаёт список допустимых content-type для загрузки посетителем. По умолчанию доступны следующие: image/png, image/jpeg, image/pjpeg, application/msword, application/rtf, image/gif, text/plain, application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document, image/webp, audio/ogg.
  • robot_allowed_upload_file_types — определяет, какие типы файлов сможет отправлять посетителю бот. По умолчанию набор допустимых типов аналогичен набору оператора: png, jpg, jpeg, doc, rtf, gif, txt, pdf, docx, webp, oga, ogg.

Механизм работы ограничений:

  • Если неизвестно расширение файла, такой файл не будет отправлен.
  • Параллельно с анализом белого списка анализируется список допустимых content-type (параметр allowed_upload_file_content_types). Если известен content-type файла и при этом он отсутствует в заданном перечне, то файл доставлен не будет.

Ограничения по размерам файла

  • max_visitor_upload_file_size — максимальный размер файла, который может загрузить посетитель. Указывается в мегабайтах и по умолчанию установлен в 10 Мб.
  • max_robot_upload_file_size — максимальный размер файла, загружаемого ботом. Указывается в мегабайтах и по умолчанию установлен в 10 Мб.

При этом ограничение по максимальному допустимому размеру файла есть и на стороне веб-сервера nginx. Необходимо, чтобы размер файла не превышал оба этих значения. Если параметр максимального допустимого размера файла в Webim больше параметра на стороне nginx (client_max_body_size) и соответствующего ему параметра nginx_upload_size в файле main.ini, то будет использовано значение параметра nginx_upload_size, по умолчанию равное 10 Мб.

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

Проверки файлов на безопасность

Отправляемые посетителями файлы проходят следующие проверки на безопасность:

  • в названиях файлов будут найдены и устранены right-to-left override;
  • будут пропускаться только те файлы, у которых расширение и content type соответствуют друг другу;
  • будут использоваться и проверяться сигнатуры ("магические числа"), а также они будут сопоставляться с расширением и content type файла.

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

  • параметр enhanced_file_security настроек account config включает безопасный режим относительно файлов, отправляемых посетителям (при значении параметра true);
  • параметр robot_enhanced_file_security включает безопасный режим относительно файлов, отправляемых роботами (при значении параметра true).

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

Оператор скачивает файл из Webim Server

  1. Оператор начинает скачивать файл из Webim Server.
  2. Веб-фронтэнд отправляет запрос файла по ссылке на веб-сервер Nginx.
    Пример ссылки: '/l/o/download/2dda66441cfc481eb2b3f8a7c33b5df/photo_2019-07-17_18-20-35.jpg'.
  3. Происходит реверсивное проксирование запросов на Python сервис.
  4. Python сервис проверяет наличие файла в файловом хранилище по пути /var/pro/client-data/cd/ACCOUNT_NAME/files и соответствие запрашиваемого имени тому, что хранится в мета-информации, производит дополнительные обработки изображений (при запросе превью изображения отдаёт файл 2dda66441cfc481eb2b3f8a7c33b5df_300x300 в разрешении 300x300 (разрешение по умолчанию)).

Схема работы сервиса при скачивании файла оператором:

Оператор загружает файл на Webim Server

  1. Оператор начинает загружать файл на Webim Server.
  2. Веб-фронтэнд отправляет файл на /l/o/action.php?action=upload_file веб-сервера Nginx.
  3. Происходит реверсивное проксирование запросов на Python сервис.
  4. Python сервис сохраняет файл и мета-информацию о нём в файловое хранилище. Имя файла генерируется как guid — например, 2dda66441cfc481eb2b3f8a7c33b5df. Мета-информация хранится в файле 2dda66441cfc481eb2b3f8a7c33b5df.desc (в соответствии с примером выше). Список хранимых полей:
    • content_type;
    • внутренний id пользователя;
    • имя файла;
    • guid;
    • объём файла.

    Сервис сохраняет файл по пути /var/pro/client-data/cd/ACCOUNT_NAME/files.

Схема работы сервиса при загрузке файла оператором:

Пользователь скачивает файл из Webim Server

  1. Пользователь начинает скачивать файл из Webim Server.
  2. Веб-фронтэнд или мобильное приложение (работает через Webim Mobile SDK) отправляет запрос файла по ссылке на веб-сервер Nginx.
    Пример ссылки для веб-фронтэнда: '/l/v/download/2dda66441cfc481eb2b3f8a7c33b5df/photo_2019-07-17_18-20-35.jpg?expires=1564763939&hash=592d5761a5d70ff96ed846e907c59206d83c6d13642a04956425026be3b78739'.
    Пример ссылки для мобильного приложения (работает через Webim Mobile SDK): '/l/v/m/download/2dda66441cfc481eb2b3f8a7c33b5df/photo_2019-07-17_18-20-35.jpg?expires=1564763939&hash=592d5761a5d70ff96ed846e907c59206d83c6d13642a04956425026be3b78739'.
  3. Происходит реверсивное проксирование запросов на Python сервис.
  4. Python сервис проверяет наличие файла в файловом хранилище по пути /var/pro/client-data/cd/ACCOUNT_NAME/files и соответствие запрашиваемого имени тому, что хранится в мета-информации, производит дополнительные обработки изображений (при запросе превью изображения отдаёт отдаёт файл 2dda66441cfc481eb2b3f8a7c33b5df_300x300 в разрешении 300x300 (разрешение по умолчанию)).

Скачивание файла через Webim Mobile SDK

  1. Ссылка на скачивание генерируется сервером. Она содержит:
    • момент запроса,
    • поле expires, в свою очередь содержащее параметр file_url_expiring_timeout, который определяет время доступа к скачиванию файла по ссылке для каналов общения (по умолчанию равняется 86400 секундам, т.е. 1 день). Для чатов из мобильного приложения время работы ссылки всегда равняется 5 минутам.
  2. Мобильное приложение получает данную ссылку от Webim Mobile SDK через метод getUrl().

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

Возможно отключение проверки expires, в таком случае ссылка будет работать бесконечно. Однако делать это не рекомендуется, поскольку это может отрицательно сказаться на безопасности при передаче файла.

Используются следующие эндпоинты:

  • /l/c/download (для каналов)
  • /l/v/m/download (для мобильных приложений)

Схема работы сервиса при скачивании файла пользователем:

Пользователь загружает файл на Webim Server

  1. Пользователь начинает загружать файл на Webim Server.
  2. Веб-фронтэнд отправляет файл на /l/v/upload (/l/v/m/upload для мобильного приложения (работает через Webim Mobile SDK)) веб-сервера Nginx.
  3. Происходит реверсивное проксирование запросов на Python сервис.
  4. Python сервис сохраняет файл и мета-информацию о нём в файловое хранилище. Имя файла генерируется как guid — например, 2dda66441cfc481eb2b3f8a7c33b5df. Мета-информация хранится в файле 2dda66441cfc481eb2b3f8a7c33b5df.desc (в соответствии с примером выше). Список хранимых полей:
    • content_type;
    • внутренний id пользователя;
    • имя файла;
    • guid;
    • объём файла.

    Сервис сохраняет файл по пути /var/pro/client-data/cd/ACCOUNT_NAME/files.

Схема работы сервиса при загрузке файла пользователем:

Привязка загруженного файла к обращению

Каждое загруженное вложение имеет свой guid-код, который его идентифицирует. Кроме этого, в метаданных файла содержится id посетителя, в чате с которым вложение загружалось. Это позволяет однозначно идентифицировать чат, в который загружается файл.

Список полей:

  • client_content_type - тип файла, заявленный его отправителем;
  • внутренний id пользователя;
  • имя файла;
  • content_type - тип файла, распознанный Webim при помощи библиотеки python-magic;
  • guid;
  • объём файла.

Пример:

{
    "client_content_type":"application/sql",
    "visitor_id":"10750f378f50c6ccdb572520f3ae9bdc",
    "filename":"filename.ext",
    "content_type":"text/plain",
    "guid":"73fff01266414934b181a93061cf26bf",
    "size":2384
}