Вы должны загрузить файл в 5MiB + кусках через многопоточный API S3 . Каждый из этих блоков требует Content-Length, но вы можете избежать загрузки огромных объемов данных (100MiB +) в память.
S3 позволяет до 10000 частей. Таким образом, выбрав размер 5MiB, вы сможете загружать динамические файлы до 50GiB. Должно быть достаточно для большинства случаев использования.
Однако: если вам нужно больше, вам нужно увеличить размер детали. Либо используя более высокий размер детали (например, 10MiB), либо увеличивая его во время загрузки.
First 25 parts: 5MiB (total: 125MiB)
Next 25 parts: 10MiB (total: 375MiB)
Next 25 parts: 25MiB (total: 1GiB)
Next 25 parts: 50MiB (total: 2.25GiB)
After that: 100MiB
Это позволит вам загружать файлы до 1 ТБ (ограничение S3 для одного файла равно 5TB прямо сейчас), не теряя память без необходимости.
Его проблема отличается от ваш - он знает и использует Content-Length перед загрузкой. Он хочет улучшить ситуацию: многие библиотеки обрабатывают загрузки, загружая все данные из файла в память. В псевдокоде, который был бы примерно таким:
data = File.read(file_name)
request = new S3::PutFileRequest()
request.setHeader('Content-Length', data.size)
request.setBody(data)
request.send()
Его решение делает это, получая Content-Length
через файловую систему-API. Затем он передает данные с диска в поток запросов. В псевдокоде:
upload = new S3::PutFileRequestStream()
upload.writeHeader('Content-Length', File.getSize(file_name))
upload.flushHeader()
input = File.open(file_name, File::READONLY_FLAG)
while (data = input.read())
input.write(data)
end
upload.flush()
upload.close()