Как реализовать передачу файла по частям с идентификатором загрузки и возобновлением
Что проверяют
Умеете ли вы спроектировать протокол, а не только цикл чтения файла кусками: где хранится состояние загрузки, как клиент узнаёт, с какого места продолжать, и что будет при повторной отправке части. Следом спрашивают про проверку целостности и уборку брошенных загрузок.
Как отвечать
Протокол из четырёх шагов:
- создание:
POST /uploadsс именем, размером и хэшем файла. Сервер возвращаетuploadId(GUID, а не счётчик) и размер части, запись о загрузке кладёт в базу или Redis с привязкой к пользователю; - передача частей:
PUT /uploads/{id}/chunks/{index}или запрос со смещением вContent-Range. Часть с тем же номером можно прислать повторно, результат не изменится, и это делает ретраи безопасными; - статус:
GETилиHEADвозвращает, какие части или сколько байт уже принято. С этого места клиент и продолжает после обрыва или перезапуска; - завершение: сервер склеивает части, сверяет SHA-256 с заявленным и только тогда помечает файл готовым.
На ASP.NET Core части не принимайте через IFormFile: он буферизирует тело, а крупное сбрасывает во временный файл. Читайте Request.Body потоком и пишите в FileStream по нужному смещению или отдельными файлами частей. Лимит тела запроса в Kestrel по умолчанию около 30 МБ: часть должна быть меньше, либо лимит поднимают атрибутом [RequestSizeLimit].
Клиент на HttpClient читает файл с переиспользуемым буфером, а ретраи с экспоненциальной задержкой берёт из Microsoft.Extensions.Http.Resilience или Polly.
Готовые решения: открытый протокол tus (есть серверная библиотека для .NET) и multipart upload в S3-совместимых хранилищах, где части грузятся по подписанным ссылкам.
Где спотыкаются
Хранят прогресс только на клиенте. После перезапуска продолжить нельзя, а сервер не знает, какие части у него целые.
Не проверяют хэш и не делают приём идемпотентным. Повторно присланная часть дописывается в конец, и файл собирается битым.
Не думают о жизненном цикле: брошенные загрузки годами занимают диск, а угадываемый uploadId без проверки владельца позволяет дописать кусок в чужой файл. Нужны TTL с фоновой очисткой и проверка, что загрузка принадлежит текущему пользователю.