Могу ли я передать потоковое видео на S3 без заголовка длины содержимого? - PullRequest
52 голосов
/ 28 декабря 2011

Я работаю на машине с ограниченной памятью, и я хотел бы загрузить динамически генерируемый (не с диска) файл в потоковом режиме на S3.Другими словами, я не знаю размер файла, когда я начинаю загрузку, но я буду знать его к концу.Обычно запрос PUT имеет заголовок Content-Length, но, возможно, есть способ обойти это, например, использовать multipart или chunked content-type.

S3 может поддерживать потоковую загрузку.Например, см. Здесь:

http://blog.odonnell.nu/posts/streaming-uploads-s3-python-and-poster/

У меня вопрос, могу ли я выполнить то же самое без указания длины файла в начале загрузки?

Ответы [ 5 ]

58 голосов
/ 16 января 2012

Вы должны загрузить свой файл в 5MiB + чанках через multipart API S3 . Для каждого из этих блоков требуется длина содержимого, но вы можете избежать загрузки в память огромных объемов данных (100 МБ +).

  • Инициирование S3 Многоэтапная загрузка .
  • Собирайте данные в буфер, пока этот буфер не достигнет нижнего предела размера фрагмента S3 (5 МБ). Генерация контрольной суммы MD5 при создании буфера.
  • Загрузите этот буфер как Part , сохраните ETag (прочитайте документы по нему).
  • Как только вы достигнете EOF ваших данных, загрузите последний кусок (который может быть меньше, чем 5MiB).
  • Завершение многочастной загрузки.

S3 позволяет до 10 000 деталей. Таким образом, выбрав размер 5 МБ, вы сможете загружать динамические файлы до 50 ГБ. Должно быть достаточно для большинства случаев использования.

Однако: если вам нужно больше, вы должны увеличить свой размер детали. Либо используя больший размер детали (например, 10 МБ), либо увеличив его во время загрузки.

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 для одного файла сейчас составляет 5 ТБ) без лишних затрат памяти.


примечание к вашей ссылке на блог Шона О'Доннелса :

Его проблема отличается от вашей - он знает и использует 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()
6 голосов
/ 14 февраля 2014

Поместите этот ответ здесь для других, если это поможет:

Если вы не знаете длину данных, которые вы передаете на S3, вы можете использовать S3FileInfo и метод OpenWrite()записать произвольные данные в S3.

var fileInfo = new S3FileInfo(amazonS3Client, "MyBucket", "streamed-file.txt");

using (var outputStream = fileInfo.OpenWrite())
{
    using (var streamWriter = new StreamWriter(outputStream))
    {
        streamWriter.WriteLine("Hello world");
        // You can do as many writes as you want here
    }
}
5 голосов
/ 05 октября 2015

Вы можете использовать инструмент командной строки gof3r для потоковой передачи каналов Linux:

$ tar -czf - <my_dir/> | gof3r put --bucket <s3_bucket> --key <s3_object>
1 голос
/ 10 апреля 2014

Если вы используете Node.js, вы можете использовать плагин, такой как s3-streaming-upload , чтобы сделать это довольно легко.

1 голос
/ 28 декабря 2011

Подробнее о запросах из нескольких частей HTTP.Вы можете отправить файл в виде кусков данных к цели.

...