Как сохранить потоки данных в S3? Пример aws-sdk-go не работает?
Я пытаюсь сохранить данный поток данных в хранилище, совместимом с S3. Размер не известен до окончания потока и может варьироваться от 5 МБ до ~500 ГБ.
Я пробовал разные возможности, но не нашел лучшего решения, чем сам осколок. Мое лучшее предположение - сделать буфер фиксированного размера, заполнить его потоком и записать в S3. Есть ли лучшее решение? Может быть, способ, где это прозрачно для меня, без записи всего потока в память?
В файле reads aws-sdk-go есть пример программы, которая берет данные из stdin и записывает их в S3: https://github.com/aws/aws-sdk-go
Когда я пытаюсь передать данные с помощью канала |
Я получаю следующую ошибку:
failed to upload object, SerializationError: failed to compute request body size
caused by: seek /dev/stdin: illegal seek
Я делаю что-то не так или пример не работает так, как я ожидаю?
Я хотя и пробовал minio-go, с PutObject() или client.PutObjectStreaming (). Это функционально, но потребляет столько же памяти, сколько и данные для хранения.
- Есть ли лучшее решение?
- Есть ли небольшой пример программы, которая может передавать произвольные данные в S3?
1 ответ
Вы можете использовать загрузчик SDK для обработки загрузок неизвестного размера, но вам нужно будет сделать os.Stdin
"невидим", завернув его в io.Reader
, Это потому что Uploader
в то время как это требует только io.Reader
в качестве тела ввода, под капотом он проверяет, является ли тело ввода Seeker
и если это так, он вызывает Seek
в теме. И с тех пор os.Stdin
это просто *os.File
который реализует Seeker
интерфейс, по умолчанию, вы получите ту же ошибку, которую вы получили от PutObjectWithContext
,
Uploader
также позволяет загружать данные в чанках, размер которых вы можете настроить, и вы также можете настроить, сколько из этих чанков должно быть загружено одновременно.
Вот модифицированная версия связанного примера, без кода, который может остаться неизменным.
package main
import (
// ...
"io"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
type reader struct {
r io.Reader
}
func (r *reader) Read(p []byte) (int, error) {
return r.r.Read(p)
}
func main() {
// ... parse flags
sess := session.Must(session.NewSession())
uploader := s3manager.NewUploader(sess, func(u *s3manager.Uploader) {
u.PartSize = 20 << 20 // 20MB
// ... more configuration
})
// ... context stuff
_, err := uploader.UploadWithContext(ctx, &s3manager.UploadInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: &reader{os.Stdin},
})
// ... handle error
}
Что касается того, является ли это лучшим решением, чем minio-go
Я не знаю, вам придется проверить это самостоятельно.