Реалізація отправки файлів у чаті мобільного додатку
PDF, XLSX, ZIP, APK — користувачи відправляють все. Задача не зводиться до кнопки «прикріпити файл»: потрібно правильно обробити file picker на обох платформах, коректно відобразити тип файлу, організувати завантаження та безпечне скачування на пристрій отримувача.
Вибір файлу: підводні камні платформ
На iOS системний UIDocumentPickerViewController повертає URL з security-scoped bookmark. Доступ до файлу відкривається через startAccessingSecurityScopedResource() та обов'язково закривається через stopAccessingSecurityScopedResource() після копіювання у тимчасову директорію. Якщо забути другий виклик — утечка security scope, та при наступному запуску додатку доступ до файлу буде заблокований системою.
Файли з iCloud Drive приходять не одразу: NSMetadataQuery показує статус завантаження. Якщо файл не скачан на пристрій — потрібно дочекатися завершення NSMetadataUbiquitousItemIsDownloadingKey перед копіюванням. Без цього отримаємо пустий файл розміром 0 байт у upload-черзі.
На Android — Intent(Intent.ACTION_OPEN_DOCUMENT) з addCategory(Intent.CATEGORY_OPENABLE). Uri з content provider неможливо напрямку передавати в сітьові запити — потрібно скопіювати вміст через contentResolver.openInputStream() у кеш-директорію додатку. Файли з Google Drive та інших провайдерів не мають реального шляху в файловій системі, лише content:// URI.
MIME-тип та іконки
Визначаємо MIME по розширенню через UTType (iOS 14+) або MimeTypeMap (Android). На сервері — додатково перевіряємо через magic bytes (перші байти файлу). PDF починається з %PDF, ZIP — з PK\x03\x04. Це захищає від переіменованих виконуваних файлів.
У чаті показуємо іконку по категорії: документ, таблиця, архів, аудіо, прочее. Не намагаємося рендерити превью для кожного типу — лише для PDF (через PDFKit на iOS або PdfRenderer на Android) та офісних форматів через QuickLook / ACTION_VIEW з системним додатком.
Завантаження та скачування
Upload — ті ж принципи, що для відео: чанкування для файлів > 5 МБ, background session на iOS, WorkManager на Android. Прогрес у байтах, не відсотках — користувач розуміє 1.2 МБ з 8.4 МБ краще, ніж 14%.
Скачування на пристрій отримувача — окрема історія. На iOS файл зберігаємо в FileManager.default.urls(for: .documentDirectory) та пропонуємо через UIActivityViewController відкрити в іншому додатку. Пряме збереження в «Файли» — через UIDocumentPickerViewController в режимі експорту.
На Android — системний DownloadManager: коректно обробляє фонову завантаження, показує прогрес у шторці сповіщень та зберігає в Downloads. Прямий путь через FileOutputStream в getExternalFilesDir() — лише для внутрішнього кеша додатку, не видного користувачу в файловому менеджері.
Безпека
Білий список MIME-типів на сервері — обов'язково. Виконувані файли (.exe, .apk, .ipa, .sh) блокуємо або перевіряємо через антивірусний скан (ClamAV, VirusTotal API). Максимальний розмір файлу — ліміт на рівні API gateway, не лише на клієнті.
Посилання на скачування — presigned URL з TTL. Прямі посилання на S3 без підпису означають публічний доступ до приватних чатів.
Терміни
Базова реалізація (file picker, upload з прогресом, відображення в чаті, скачування) — 2–3 дні. Поддержка background upload + возобновлення + білий список типів — ще 1 день. Вартість рассчитується індивідуально.







