Пишу бекэнд на расте и Axum. Делаю загрузку файла multipart/form-data.
Грузить файл предполагается как-то так:
// Обработчик запроса принимает параметр mut multipart: Multipart
while let Some(mut field) = multipart.next_field().await? {
if let Some("file") = field.name() { // Ищем нужное имя поля
while let Some(chunk) = field.chunk().await? {
// Делаем что-то с очередным куском файла (Bytes)
}
// Файл закончился
}
}
Как я понял по документации, это единственный асинхронный способ. У Field есть ещё методы bytes() и text(), но они грузят содержимое файла полностью в ОЗУ и возвращают целиком Bytes или String.
А библиотека rust-s3 имеет вот такой метод у Bucket:
pub async fn put_object_stream<R: AsyncRead + Unpin>(
&self,
reader: &mut R,
s3_path: impl AsRef<str>,
) -> Result<u16, S3Error>
То есть мне надо как-то превратить field в AsyncRead. При этом я категорически не хочу грузить файл целиком в ОЗУ или сохранять во временный каталог на диск. Хочу напрямую от клиента в S3 пересылать файл (но при этом S3 хранилище напрямую клиенту недоступно, потому что там ещё определённая бизнес-логика навёрнута на загрузке файлов, плюс контроль доступа).