2016-06-09 3 views
11

S3에서 파일을 다운로드하고 해당 파일을 S3의 다른 버킷에 업로드하려고합니다. Copy API는 사용하지 말라고 했으므로 여기서 작동하지 않습니다. S3에서 개체를 얻기io.ReadClasser에서 io.ReadSeeker로 어떻게 이동합니까?

페이로드는 io.ReadSeekerBody 소요 io.ReadCloser의 해당 파일을 업로드 할 response.Body 있습니다.

내가 알아낼 수있는 유일한 방법은 response.Body을 파일에 저장 한 다음 해당 파일을 io.ReadSeeker으로 전달하는 것입니다. 이렇게하려면 전체 파일을 디스크에 먼저 쓰고 디스크에서 전체 파일을 읽어야합니다.이 파일은 꽤 잘못 들립니다.

내가 뭘하고 싶은 것입니다 :

resp, _ := conn.GetObject(&s3.GetObjectInput{Key: "bla"}) 
conn.PutObject(&s3.PutObjectInput{Body: resp.Body}) // resp.Body is an io.ReadCloser and the field type expects an io.ReadSeeker 

질문은, 어떻게 가능한 가장 효율적인 방법에 io.ReadSeekerio.ReadCloser에서 가야합니까?

+0

사용중인 특정 API 및 기능은 무엇입니까? Go S3 SDK에서 언급 한 기능을 찾지 못하는 것 같습니다. https://docs.aws.amazon.com/sdk-for-go/api/service/s3.html – BadZen

+0

@BadZen 내가 사용할 전화를 추가했습니다. – Jeff

+0

복사 기능을 사용할 수 없다는 것은 이상한 일입니다. 어쩌면 그걸 다시 밀어 넣을 수 있습니다. 파일을 디스크에 쓰는 것 외의 유일한 옵션은'io.ReadSeeker' 탐색 요청에서 GetObject()를 다시 실행하고 범위 필드를 탐색 위치에서 시작하도록 설정합니다. 그것은 모든면에서 이미 디스크에 쓰기 오류보다 나쁜 해결책입니다. – BadZen

답변

7

io.ReadSeeker은 기본 Read()Seek() 방법을 그룹화하는 인터페이스입니다. Seek() 방법의 정의 :

Seek(offset int64, whence int) (int64, error) 

Seek() 방법의 구현은 어디서나 가능하거나 재현 할 수 모든 소스를 필요로하는 소스의를 추구 할 수 있도록해야합니다. 파일이 완벽한 예이고 파일은 디스크에 영구 저장되며 언제든지 파일의 일부를 읽을 수 있습니다.

response.Body은 기본 TCP 연결을 읽도록 구현됩니다. 기본 TCP 연결을 읽으면 상대방의 클라이언트가 보내는 데이터를 얻을 수 있습니다. 데이터는 캐시되지 않으며 클라이언트는 요청시 데이터를 다시 보내지 않습니다. 그렇기 때문에 response.Bodyio.Seeker (따라서 io.ReadSeeker)을 구현하지 않습니다. 그 요청에 따라이 어디 있다는 점에서 추구 할 수 있도록

그래서 io.Reader 또는 io.ReadCloser에서 io.ReadSeeker를 얻기 위해, 당신은 모든 데이터를 캐시 뭔가를해야합니다. 당신이 언급 한 바와 같이

이 캐싱 메커니즘은 파일에 기록 할 수있다, 또는 당신은 ioutil.ReadAll()를 사용하여 []byte로, 메모리에 모든 것을 읽을 수 있습니다, 그리고 당신은 []byte에서 io.ReadSeeker을 얻기 위해 bytes.NewReader()를 사용할 수 있습니다. 물론이 작업에는 한계가 있습니다. 모든 내용이 메모리에 저장되어야하며,이 파일 복사 작업을 위해 해당 양의 메모리를 예약하지 않을 수도 있습니다.

모두 모두

io.Seeker 또는 io.ReadSeeker의 구현은 그래서 당신의 최선의 파일로 작성, 또는 모든 읽기 작은 파일을 []byte에 그 바이트의 컨텐츠를 스트리밍, 사용할 수있는 모든 소스 데이터를 필요 일부분.

8

io.Reader을 입력으로 사용하는 github.com/aws/aws-sdk-go/service/s3/s3manager.Uploader을 사용하십시오.

나는 PutObject이 대신 io.Readerio.ReadSeeker이 S3하는 요청이 서명 (및 콘텐츠 길이) 할 필요가있다 필요하지만 모든 데이터를 때까지 당신이 서명을 생성 할 수없는 이유를 상상한다. 이렇게하는 스트림 - y 방법은 들어오는대로 입력을 청크로 버퍼링하고 다중 청크 업로드 API를 사용하여 각 청크를 개별적으로 업로드하는 것입니다. 이것은 (내 생각) s3manager.Uploader이 무대 뒤에서하는 일입니다.

관련 문제