Skip to content

🇬🇧 English | 🇺🇦 Українська

← До змісту

11. Поширені запитання

Короткі відповіді на те, що запитують найчастіше, з посиланням на розділ, де кожне питання розібрано докладно. Якщо відповідь тут суперечить розділу — правий розділ.


Початок роботи

Скільки нод потрібно, щоб завантажити файл?

Три:

Get S3 Subsystem  →  Get Default S3 Client  →  S3 Upload File

Створювати клієнта й тримати його у змінній не треба — підсистема робить це за вас. Див. 1. Швидкий старт.

Що вписувати в Local File Path?

Або абсолютний шлях (C:/Users/You/Desktop/save.png на Windows, /Users/You/Desktop/save.png на Mac), або відносний кореня проєкту (Saved/Screenshots/shot.png) — плагін сам розгортає другий варіант однаково і в редакторі, і в зібраній грі. Шлях ассета на кшталт /Game/... не підходить: це посилання на об'єкт у Content Browser, а не на файл на диску. Повний розбір із таблицею прикладів під кожну платформу — у розділі «Шлях до файлу: абсолютний чи відносний».

Як завантажити текст через S3 Upload Bytes? Пін Data вимагає масив байтів, а не рядок

Unreal справді не має штатної ноди «рядок у байти» — скористайтеся нодою плагіна String To UTF-8 Bytes: вона перетворює FString на потрібний TArray<uint8> без позначки порядку байтів, тож "Welcome" стане рівно сімома байтами й опиниться в об'єкті словом Welcome, без нічого зайвого. Зворотна нода — UTF-8 Bytes To String, для читання невеликого текстового об'єкта назад після S3 Download Bytes. Повний граф із прикладом — у розділі «Як надіслати текст».

Чи потрібен C++?

Ні. Кожна операція доступна нодою, включно з підписаними посиланнями, метаданими й скасуванням. C++ потрібен лише для власного провайдера облікових даних чи власного транспорту — див. 6. C++ API.

Чи потрібні сторонні бібліотеки або AWS SDK?

Ні. Плагін використовує лише модуль HTTP рушія й власну реалізацію SHA-256 і підпису. Нічого встановлювати не треба.

Плагін працює лише з Amazon?

Ні. Перевірено на Amazon S3, Cloudflare R2, Backblaze B2, Google Cloud Storage, MinIO і Wasabi; у списку провайдерів є ще DigitalOcean Spaces (поки не перевірений так само), а Custom дозволяє вказати будь-який сумісний сервіс вручну. Див. 8. Провайдери.

Змінні оточення називаються AWS_ACCESS_KEY_ID і подібно за домовленістю, яку читають усі інструменти, а не тому, що потрібен Amazon.


Налаштування

Test Connection зелений, а з гри не працює. Чому?

Найімовірніше — через ключі. У редакторі плагін може брати їх із секцій, яких у зібраній грі не існує (це навмисно: те, що ви вписали в редакторі, не може поїхати у збірку).

Перевірте, що Credential Source описує спосіб, який справді працюватиме в бою, і що відповідне джерело налаштоване. Див. «Як плагін шукає ключі».

У чому різниця між Project Settings і ассетом S3 Storage Profile?

Project Settings описує одне сховище — те, з яким проєкт працює переважно. Ассет профілю — будь-яке інше: його можна підключити в ноду чи змінну, і редагується він в одному місці.

Якщо сховище одне — вистачить налаштувань. Якщо їх кілька — профілі. Див. 2. Налаштування.

Get Named S3 Client — що вписувати в Client Name?

Рядок, який придумуєте ви самі — це не ідентифікатор від S3 чи від бекенда, а лише ключ у внутрішньому кеші підсистеми. Головне — вживати той самий рядок щоразу, коли потрібен той самий клієнт; інше ім'я чи інший регістр створить другий, ще не налаштований клієнт. Щоб дістати вже створений клієнт деінде в графі, не збираючи Config вдруге, — нода Find Named S3 Client. Докладніше, з прикладом графа — «Конфігурація відома лише в рантаймі».

Я змінив ключі, а плагін користується старими

Клієнт кешує те, що вже отримав. Викличте Forget Profile Client (для профілю) або Clear Runtime Credentials (для ключів, заданих кодом) — наступне звернення створить клієнта наново.

Що вписувати в Region, якщо у провайдера немає регіонів?

Будь-яке несуперечливе значення; підійде us-east-1. Порожнім лишати не можна: регіон бере участь у формуванні підпису, навіть коли провайдер його не перевіряє. Для Cloudflare R2 потрібен саме літерал auto.

Endpoint URL лишати порожнім чи ні?

Порожнім — для Amazon S3 і Google Cloud Storage: у них відома адреса за замовчуванням, і для Amazon правильний регіональний хост обчислюється з поля Region. Для решти адресу треба вказати — вона залежить від вашого облікового запису або розгортання.


Помилки

SignatureDoesNotMatch — з чого починати?

З Path Style Addressing. Amazon хоче його вимкненим, практично всі інші — увімкненим, і помилка через це виглядає саме так, нічого не кажучи про причину. Найпростіше — обрати провайдера зі списку, тоді значення проставиться саме.

Наступний підозрюваний — регіон: він частина підпису.

The AWS Access Key Id you provided does not exist in our records

Три причини за спаданням імовірності:

  1. Використовується не той ключ — наприклад, ключ від MinIO пішов до Amazon. Перший рядок звіту називає джерело; див. 3. Облікові дані.
  2. Тимчасовий ключ без Session Token — без токена він виглядає неіснуючим.
  3. Ключ справді видалено або він від іншого облікового запису.

NoSuchBucket, хоча бакет є

Перевірте, що бакет справді в тому регіоні, який вказано, і що ім'я не містить друкарської помилки. На MinIO бакети не створюються самі — скористайтеся нодою S3 Create Bucket, консоллю MinIO або mc mb.

Перелік бакетів на Cloudflare R2 повертає 403

R2 не реалізує цю операцію. Решта операцій працює нормально; бакети створюйте й переглядайте в панелі Cloudflare.

Отримую 403 там, де очікую 404

Так поводяться провайдери, коли ключ не має права навіть бачити, існує об'єкт чи ні. Це нормально: перевіряйте політику доступу, а не наявність об'єкта.

Cannot read <шлях> на завантаженні файлу

Файла немає саме там, куди веде значення Local File Path. Якщо шлях відносний (наприклад Saved/Screenshots/shot.png), він розгортається відносно кореня проєкту, а не поточної теки в провіднику ОС і не теки, де лежить сама гра. Перевірте файл за адресою <Корінь проєкту>/Saved/Screenshots/shot.png — саме туди дивиться плагін. Докладніше — «Шлях до файлу: абсолютний чи відносний».

Помилки немає, але й даних немає

Перевірте Result Code, а не лише пін On Success. Пакетне видалення може завершитися частковим успіхом; порожній перелік — це успіх із нулем елементів, а не помилка. Див. 7. Помилки та діагностика.


Передавання

Який розмір файлу вважається великим?

Усе, що перевищує Multipart Part Size Bytes (за замовчуванням 5 МБ), автоматично йде багаточастинним завантаженням, кілька частин одночасно. Нічого вмикати не треба.

Скільки пам'яті займе завантаження файлу на 2 ГБ?

Порядку кількох буферів розміром із частину, а не 2 ГБ: файл читається в міру надсилання. Зчитування так само пишеться на диск у міру надходження.

Як показати прогрес?

Пін On Progress є в кожної ноди передавання. Він дає надіслані байти, загальний розмір і частку — цього достатньо для смужки прогресу. Див. 5. Передавання файлів.

Як скасувати передавання?

Пін On Started віддає дескриптор; збережіть його у змінну й викличте Cancel. Скасування багаточастинного завантаження скасовує його й на боці провайдера, щоб надіслані частини не залишалися в бакеті — невидимими в переліку й оплачуваними.

Чи можна відновити перерване завантаження?

Так, якщо йдеться про завантаження файлу з диска в сховище (upload). Плагін запам'ятовує ідентифікатор багаточастинного завантаження, і наступна спроба того самого файлу питає провайдера, які частини вже на місці, та досилає лише відсутні. Увімкнено за замовчуванням — Resume Interrupted Uploads у секції Transport.

Відновлення не відбудеться, якщо файл змінився (розмір або час зміни) чи змінився розмір частини: тоді файл розрізався б інакше, і об'єкт зібрався б із двох різних версій. У цьому разі завантаження чесно починається спочатку.

Дані з пам'яті (S3 Upload Bytes) не відновлюються: після перезапуску процесу їх уже немає.

Зворотний бік цієї поведінки: обірване завантаження навмисно лишається в бакеті, а його частини оплачуються. Задайте бакету правило S3 Set Incomplete Upload Cleanup, щоб те, що ніхто не продовжив, прибиралося саме.

Що конкретно відбувається, якщо гравець вимкне гру на середині завантаження?

На прикладі: файл більший за 5 МБ, S3 Upload File дійшов до 30% — і в цю мить гравець закрив гру, без жодного плавного вимкнення.

Поки все йде нормально. Плагін ріже файл на частини (типово по 5 МБ) і шле кілька одночасно (Max Concurrent Parts, за замовчуванням 4). Щойно провайдер підтвердив початок багаточастинного завантаження й видав UploadId, плагін одразу, не наприкінці, записує на диск гравця запис-нагадування — під Saved/S3/Uploads/: у якому бакеті, за яким ключем і з яким UploadId. Кожна частина, яку провайдер уже прийняв, лежить у нього фізично й назавжди (доки її не скасують) — на 30% це, умовно, 3 частини з 10.

Гравець вимикає гру. Плавне закриття не потрібне — і це головне: зберігати вже нема чого, все важливе вже або в провайдера (готові частини), або на диску (запис-нагадування). Частина, яка саме летіла мережею в момент вимкнення, просто обривається на півдорозі: провайдер не зарахує її як готову (не збіжиться розмір), тож вона зникає безслідно — не пошкодженою, а такою, ніби її й не надсилали.

Гравець запускає гру знову й тисне «Завантажити» — той самий файл, бакет і ключ. Та сама нода S3 Upload File, без жодної окремої кнопки «Продовжити». Плагін сам:

  1. знаходить запис-нагадування;
  2. звіряє файл: той самий розмір і час зміни, що на старті? Якщо файл встигли відредагувати — плагін не ризикує, викидає запис і завантажує все наново;
  3. якщо файл той самий — питає самого провайдера, а не свій запис, які частини він реально тримає під цим UploadId;
  4. відповідь «є частини 1, 2, 3» — і плагін досилає лише 4–10; перші три не йдуть повторно;
  5. прогрес одразу показує чесні 30%, а не починається з нуля.

Коли всі частини на місці, плагін каже провайдеру зібрати з них готовий об'єкт, і запис-нагадування видаляється — він більше не потрібен.

Якщо гравець більше ніколи не продовжить це завантаження — ті три частини все одно лежать у провайдера й тарифікуються, просто невидимі в звичайному переліку об'єктів. Саме для цього й існує S3 Set Incomplete Upload Cleanup із питання вище.

Чи можна відновити перерване зчитування?

Так — нодою S3 Download File Chunked. Увімкнено за замовчуванням: Resume Interrupted Downloads у секції Transport.

Звичайне S3 Download File починає наново: це один потоковий запит, а продовжити з середини можна лише діапазонами. Тому для файлу, втрата якого на половині має значення, беріть чанкову ноду.

Байти лягають у <файл>.s3part поруч із призначенням і потрапляють на місце лише зібраними повністю — за шляхом призначення обрізаний файл не з'являється ніколи. Скільки вже зчитано — це розмір самого .s3part, окремого лічильника немає.

Об'єкт звіряється за entity tag на кожному діапазоні (заголовком If-Match, а також порівнянням ETag і розміру у відповіді). Якщо об'єкт змінився:

  • виявлено на першому діапазоні продовження — .s3part викидається, об'єкт зчитується з нуля;
  • виявлено посеред зчитування — операція завершується з Precondition Failed, а недороблений файл видаляється.

Склеїти хвіст нової версії з головою старої плагін не дасть за жодних обставин: такої помилки не видно ані за розміром, ані за тим, що файл читається.

Розмір шматка між спробами може бути іншим — діапазон починається з будь-якого байта. Це відрізняється від завантаження в сховище, де розмір частини змінювати не можна.

Докладно — 5. Передавання файлів.

Передавання «зависає» на повільному з'єднанні

Підніміть Timeout Seconds: він застосовується до однієї спроби. Запит, що вичерпав усі повтори, може зайняти приблизно (Max Retries + 1) × Timeout плюс затримки між спробами.


Мультиплеєр і сервер

Плагін реплікує щось по мережі?

Ні. Він робить HTTP-запити з того процесу, у якому його викликали. Питання «як воно працює в мультиплеєрі» зводиться до питання «у якому процесі я викликаю ноду». Див. 10. Сценарії розгортання.

У сесії на вісьмох файл завантажується вісім разів

Blueprint-подія виконується на всіх. Якщо операція має бути одна — захистіть її перевіркою Has Authority (нода Switch Has Authority).

Чи працює плагін на виділеному сервері без світу?

Так. Затримки між повторами відлічує FTSTicker, а не таймер світу, тож операції коректно виконуються під час завантаження карти, у консольній утиліті й у commandlet.

Як дати клієнтам доступ, не роздаючи ключі?

Підписаними посиланнями: сервер підписує адресу й віддає її клієнтові, клієнт робить за нею звичайний запит. Клієнт при цьому налаштований як Anonymous.


Безпека

Чи можна просто вшити ключ у гру?

Технічно так, практично — вважайте його оприлюдненим. Щоб підписати запит, ключ мусить бути в пам'яті у відкритому вигляді; шифрування ассетів не допомагає, бо ключ розшифрування лежить у тому самому бінарнику.

Виняток один: ключ лише на читання для справді публічного вмісту. Перевірте себе питанням «що станеться, якщо він завтра з'явиться на форумі».

Чому в налаштуваннях немає поля для ключа?

Тому що воно збереглося б у DefaultGame.ini — файл їде і в систему контролю версій, і у збірку. З тієї самої причини полів немає в ассеті профілю: ассети кукаються.

Наскільки надійне локальне сховище ключів?

Воно захищає від читання очима, від витоку через резервну копію й від перенесення файлу на іншу машину. Воно не захищає від того, хто вже виконує код на цій машині від імені цього користувача. Це рівень більшості настільних застосунків без інтеграції із системним сховищем ключів; за потреби реалізуйте IDemoS3CredentialsStore поверх Keychain, DPAPI чи libsecret.

Секрет не потрапляє в логи?

Ні за якої багатослівності. У логах видно ідентифікатор ключа й довжину секрету, але не сам секрет.


Різне

Чи можна працювати з кількома сховищами одночасно?

Так. Заведіть ассет профілю на кожне й беріть клієнта нодою Get S3 Client For Profile. Клієнти незалежні: свої адреси, регіони й ключі.

Чим теги відрізняються від User Metadata?

Метадані задаються під час запису об'єкта, і змінити їх можна лише переписавши об'єкт (S3 Set Metadata копіює його сам у себе, оновлюючи час останньої зміни). Теги змінюються одним запитом будь-коли, об'єкт при цьому не чіпається, і їх — на відміну від метаданих — бачать правила життєвого циклу та політики доступу на боці провайдера.

Правило просте: незмінне — у метадані, змінне — у теги. Порівняльна таблиця й приклад — у розділі «Теги чи метадані».

Мене турбують незавершені завантаження — за них справді платять?

Так. Частини перерваного багаточастинного завантаження лишаються в бакеті, оплачуються як сховище й при цьому не видно у переліку об'єктів — тобто про них легко не знати роками. Плагін до того ж навмисно не скасовує обірване завантаження, щоб його можна було продовжити.

Виконайте один раз для кожного бакета ноду S3 Set Incomplete Upload Cleanup (сім днів — розумне значення): провайдер сам прибиратиме те, що ніхто так і не продовжив. Докладніше — «Правила життєвого циклу».

Чи можна створити бакет із гри?

Так, нода S3 Create Bucket. На MinIO це часто необхідно, бо бакети там не створюються самі. На Amazon імена бакетів глобально унікальні серед усіх клієнтів, тож правдоподібне ім'я зазвичай уже зайняте — це нормально.

Ключі об'єктів із пробілами й кирилицею працюють?

Так, і це перевірено наскрізними тестами на всіх шести сервісах саме таким ключем — із пробілом, амперсандом, кирилицею та плюсом. Якщо імена об'єктів походять від введення користувача, перевірте цей випадок і у себе.

Як подивитися справжній HTTP-трафік?

Log LogDemoS3 Verbose       // по рядку на запит
Log LogDemoS3 VeryVerbose   // ще й підписані заголовки

Тестовий модуль потрапляє у зібрану гру?

Ні. Він має тип DeveloperTool: збирається для редактора й Development-конфігурацій і ніколи не потрапляє в Shipping.


Назад: До змісту

Далі: 12. Консоль розробника