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

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

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

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

Ограничения, связанные с обменом файлами в чате, регламентируются системными настройками, которые указываются в специальном [табличном редакторе настроек аккаунта](https://webim.ru/kb/for-admins/service-pages/account-config-editor.html) (`account-config`), которые размещаются по отдельному URL-адресу. Если у Вас есть к нему доступ, Вы можете редактировать настройки самостоятельно, в противном случае попросите об этом [техническую поддержку](mailto:support@webim.ru) **Webim**.

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

  * `visitor_upload_file` определяет, могут ли посетители отправлять файлы в чат. По умолчанию `true`.

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

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

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

  * `allowed_upload_file_types` — задаёт список расширений файлов, которые посетителю разрешается отправлять (белый список). По умолчанию указаны следующие типы файлов: `3gp`, `avi`, `doc`, `docx`, `flv`, `gif`, `jpe`, `jpeg`, `jpg`, `mkv`, `mov`, `mp3`, `mp4`, `mpeg`, `mpg`, `oga`, `ogg`, `pdf`, `png`, `rtf`, `txt`, `wav`, `webm`, `webp`, `wma`, `wmv`.

  * `allowed_upload_file_content_types` — задаёт список допустимых content-type для загрузки посетителем. По умолчанию доступны следующие: `application/msword`, `application/ogg`, `application/pdf`, `application/rtf`, `application/vnd.openxmlformats`, `application/vnd.openxmlformats-officedocument.wordprocessingml.document`, `application/x-ogg`, `application/x-rtf`, `audio/mp3`, `audio/mpeg`, `audio/ogg`, `audio/wav`, `audio/webm`, `audio/x-m4a`, `audio/x-ms-wma`, `audio/x-ogg`, `audio/x-pn-wav`, `audio/x-vorbis+ogg`, `audio/x-wav`, `image/gif`, `image/jpeg`, `image/jpg`, `image/pjpeg`, `image/png`, `image/webp`, `text/plain`, `text/richtext`, `text/rtf`, `video/3gpp`, `video/avi`, `video/mkv`, `video/mp4`, `video/mpeg`, `video/mpg`, `video/ogg`, `video/quicktime`, `video/webm`, `video/x-flv`, `video/x-matroska`, `video/x-mkv`, `video/x-ms-asf`, `video/x-ms-wmv`, `video/x-msvideo`, `video/x-ogg`, `video/x-theora+ogg`.

  * `robot_allowed_upload_file_types` — определяет, какие типы файлов сможет отправлять посетителю бот. По умолчанию набор допустимых типов аналогичен набору оператора: `3gp`, `avi`, `doc`, `docx`, `flv`, `gif`, `jpe`, `jpeg`, `jpg`, `mkv`, `mov`, `mp3`, `mp4`, `mpeg`, `mpg`, `oga`, `ogg`, `pdf`, `png`, `rtf`, `txt`, `wav`, `webm`, `webp`, `wma`, `wmv`.

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

  * Если неизвестно расширение файла, такой файл не будет отправлен.

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

!!! Note "N.B." 
    Форматы изображений **HEIC/HEIF** в данный момент не поддерживаются в Webim. Даже если расширения `heic`/`heif` и соответствующие `content-type` добавить в параметры `allowed_upload_file_types` и `allowed_upload_file_content_types`, такие файлы будут отклонены сервером и не отобразятся в интерфейсе оператора и пользовательских приложениях. Рекомендуется конвертировать изображения из **HEIC/HEIF** в другие форматы (например, `jpeg` или `png`) до отправки.

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

  * `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 Мб.

Если посетитель или оператор отправляет файл недопустимого типа либо файл, размер которого превышает установленные ограничения, в чате отобразится соответствующее системное сообщение. 
**Ограничения по размеру действуют и для оператора**: на этапе загрузки применяется параметр `nginx_upload_size` (см. `main.ini`), а при отправке из почтового канала дополнительно действует лимит почтового сервера на одно письмо. Если суммарный размер вложений превышает лимит письма, отправка выполняется несколькими письмами; если один файл больше лимита письма, для него фиксируется ошибка и письмо не отправляется.

---

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

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

  * В названиях файлов будут найдены и устранены [right-to-left override](https://unicode-explorer.com/c/202E);

  * Будут пропускаться только те файлы, у которых расширение и `content-type` соответствуют друг другу;

  * Будут использоваться и проверяться сигнатуры ("магические числа"), а также они будут сопоставляться с расширением и `content-type` файла.

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

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

  * Параметр `robot_enhanced_file_security` включает безопасный режим относительно файлов, отправляемых роботами (при значении параметра `true`).

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

---

## Варианты взаимодействия с файлами

Ниже представлены 4 возможных варианта взаимодействия с файлами в сервисе **Webim**.

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

  1. Оператор начинает скачивать файл из **Webim Server**.

  1. Веб-фронтэнд отправляет запрос файла по ссылке на веб-сервер **nginx**.

     Пример ссылки: `/l/o/download/2dda66441cfc481eb2b3f8a7c33b5df/photo_2019-07-17_18-20-35.jpg`.

  1. Происходит реверсивное проксирование запросов на **Chat Backend**.

  1. **Chat Backend** проверяет наличие файла в файловом хранилище по пути `/var/pro/client-data/cd/ACCOUNT_NAME/files` и соответствие запрашиваемого имени тому, что хранится в мета-информации, производит дополнительные обработки изображений (при запросе превью изображения отдаёт файл `2dda66441cfc481eb2b3f8a7c33b5df_300x300` в разрешении 300x300 (разрешение по умолчанию)).

![Схема работы сервиса при скачивании файла оператором](https://webim.ru/kb/img/devops/download-file-scheme/operator-file-download.webp){ style="width: 530px; max-width: 100%" }

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

  1. Оператор начинает загружать файл на **Webim Server**.

  1. Веб-фронтэнд отправляет файл на `/l/o/action.php?action=upload_file` веб-сервера **nginx**.

  1. Происходит реверсивное проксирование запросов на **Chat Backend**.

  1. **Chat Backend** сохраняет файл и мета-информацию о нём в файловое хранилище. Имя файла генерируется как `guid` — например, `2dda66441cfc481eb2b3f8a7c33b5df`. Мета-информация хранится в файле `2dda66441cfc481eb2b3f8a7c33b5df.desc` (в соответствии с примером выше). Список хранимых полей:

    * `content_type`

    * Внутренний id пользователя

    * Имя файла

    * `guid`

    * Объём файла

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

![Схема работы сервиса при загрузке файла оператором](https://webim.ru/kb/img/devops/download-file-scheme/operator-file-upload.webp){ style="width: 530px; max-width: 100%" }

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

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

  1. Веб-фронтэнд или мобильное приложение (работает через **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`.

  1. Происходит реверсивное проксирование запросов на **Chat Backend**.

  1. **Chat Backend** проверяет наличие файла в файловом хранилище по пути `/var/pro/client-data/cd/ACCOUNT_NAME/files` и соответствие запрашиваемого имени тому, что хранится в мета-информации, производит дополнительные обработки изображений (при запросе превью изображения отдаёт отдаёт файл `2dda66441cfc481eb2b3f8a7c33b5df_300x300` в разрешении 300x300 (разрешение по умолчанию)).

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

  1. Ссылка на скачивание генерируется сервером. Она содержит:

    * Момент запроса

    * Поле `expires`, в свою очередь содержащее параметр `file_url_expiring_timeout`, который определяет время доступа к скачиванию файла по ссылке для каналов общения (по умолчанию равняется `86400` секундам, т.е. 1 день). Для чатов из мобильного приложения время работы ссылки всегда равняется 5 минутам.

  1. Мобильное приложение получает данную ссылку от **Webim Mobile SDK** через метод `getUrl()`.

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

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

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

  * `/l/c/download` (для каналов)

  * `/l/v/m/download` (для мобильных приложений)

![Схема работы сервиса при скачивании файла пользователем](https://webim.ru/kb/img/devops/download-file-scheme/visitor-file-download.webp){ style="width: 780px; max-width: 100%" }

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

  1. Пользователь начинает загружать файл на **Webim Server**.

  1. Веб-фронтэнд отправляет файл на `/l/v/upload` (`/l/v/m/upload` для мобильного приложения (работает через **Webim Mobile SDK**)) веб-сервера **nginx**.

  1. Происходит реверсивное проксирование запросов на **Chat Backend**.

  1. **Chat Backend** сохраняет файл и мета-информацию о нём в файловое хранилище. Имя файла генерируется как `guid` — например, `2dda66441cfc481eb2b3f8a7c33b5df`. Мета-информация хранится в файле `2dda66441cfc481eb2b3f8a7c33b5df.desc` (в соответствии с примером выше). Список хранимых полей:

    * `content_type`

    * Внутренний id пользователя

    * Имя файла

    * `guid`

    * Объём файла

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

![Схема работы сервиса при загрузке файла пользователем](https://webim.ru/kb/img/devops/download-file-scheme/visitor-file-upload.webp){ style="width: 785px; max-width: 100%" }

## Режим хранения в S3

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

  * При включенном `use_s3_storage` файлы сохраняются в S3 согласно структуре ключей `<YYYY>/<MMDD>/<G1>/<G2>/<GUID>.<ext>` (см. раздел [«Параметры настроек сервера»](https://webim.ru/kb/devops/server-account-config-parameters.html) и таблицу параметров).

  * Для каналов, не поддерживающих вложения, операторские файлы доставляются как защищенные ссылки (пресайнд-URL) с ограниченным сроком жизни (см. [тайм-ауты](https://webim.ru/kb/for-admins/time-outs-list.html)).

  * Старые файлы (загруженные до включения S3) продолжают обслуживаться из файловой системы.

!!! warning "Внимание!"
    При недоступности S3 операции с файлами недоступны до восстановления соединения.

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

Каждое загруженное вложение имеет свой 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
}
```

---

Источник: https://webim.ru/kb/devops/download-file-scheme.html
