SMeet Mini Apps
Файлы
Файл, который загрузил человек, это его содержимое, а не ваше. Он никогда не открывается как страница на вашем origin: мост SMeet доверяет любому документу этого origin, поэтому загруженный HTML или SVG, показанный там, действовал бы как ваше приложение.
Загрузка#
- Человек выбирает файл стандартным
<input type="file">. Покажите, кому он уходит: вашему серверу, а не SMeet. - Загружайте его на свой сервер со своей сессией, после
checkSession(Проверка сессии). Показывайте ход загрузки, давайте её отменить и повторяйте прерванную. - Храните файл вместе с черновиком на сервере, по приложению, среде, человеку и пространству, чтобы при повторном открытии окна человек нашёл файл уже загруженным.
- Имя, которое дал человек, храните только как текст: уберите путь и управляющие символы, сократите и показывайте через
textContent, никогда как разметку.
Отдача файлов#
Файл человека отдаётся обратно только как скачивание, никогда на месте страницы:
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="report.pdf"; filename*=UTF-8''report.pdf
X-Content-Type-Options: nosniff
Content-Security-Policy: sandboxContent-Type: application/octet-streamнезависимо от типа, который браузер указал при загрузке: указанный тип это слово человека, аtext/htmlилиimage/svg+xmlисполнились бы как страница на вашем origin.Content-Disposition: attachmentвсегда, никогдаinline.X-Content-Type-Options: nosniff, чтобы браузер не угадывал тип, а файл не мог служить и источником<script>или стиля.Content-Security-Policy: sandbox, чтобы даже открытый всё-таки файл работал как документ без origin, без полномочий вашего приложения.- Проверяйте сессию перед каждым скачиванием и отдавайте файл только его владельцу и тем, кому ваше приложение разрешает его видеть.
Пример службы заявок собирает заголовок так:
export function attachmentDisposition(name) {
const ascii = name.replace(/[^\x20-\x7e]/g, '_').replace(/["\\;]/g, '_');
const encoded = encodeURIComponent(name).replace(/['()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
return `attachment; filename="${ascii}"; filename*=UTF-8''${encoded}`;
}Это правило 4.4 из Правил для авторов: никакого пользовательского и чужого HTML на origin мини-приложения.
Файлы на другом origin#
Вместо этого можно отдавать файлы людей с отдельного origin, который не является origin мини-приложения, например https://files.example.net. Этот origin SMeet никогда не встраивает, и к мосту он не подключается. Заголовки из раздела выше полезны и там.
Скачивание в окне web#
В web-версии SMeet окно не разрешает скачивание: ссылка с download или ответ с attachment, начатые изнутри окна, ничего не делают. Отдайте человеку его файл иначе:
- пришлите копию в чат через бота (ниже): человек откроет её из чата в любом приложении;
- или покажите содержимое файла на странице как текст.
Копия в чат#
Ваш сервер может отправить файл человеку через бота: uploadFile, затем, когда файл проверен и в состоянии ready, sendDocument в chat.id с expected_access_revision операции, через outbox (Outbox). Файл, не прошедший проверку (rejected, scan_failed), даёт видимую ошибку уведомления; заново с новым ключом он не отправляется. Для файлов ботов в SMeet должна быть включена поддержка файлов (Файлы в Bot API).
Лимиты#
Размер загрузки задаёт ваш сервер. Файл, который уходит в чат, ограничен Bot API: до 20 МиБ для документа.