Как прочитать файл CSV из S3 - PullRequest
       1

Как прочитать файл CSV из S3

0 голосов
/ 28 сентября 2018

У меня есть следующий код:

package main

import (
    "encoding/csv"
    "fmt"
    "io/ioutil"
    "path"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
    "github.com/aws/aws-sdk-go/service/s3/s3iface"
)

var (
    // TOKEN = os.Getenv("TOKEN")
    svc s3iface.S3API
)

func main() {    
    // Panics if there is an error in creating session
    svc = s3iface.S3API(s3.New(session.Must(session.NewSession())))

    lambda.Start(Handler)
}

func Handler(evt events.S3Event) error {

    for _, rec := range evt.Records {

        key := rec.S3.Object.Key

        dir, file := path.Split(key)
        // Download the file from S3
        obj, err := svc.GetObject(&s3.GetObjectInput{
            Bucket: aws.String(rec.S3.Bucket.Name),
            Key:    aws.String(key),
        })
        if err != nil {
            return fmt.Errorf("error in downloading %s from S3: %s\n", key, err)
        }

        body, err := ioutil.ReadAll(obj.Body)
        if err != nil {
            return fmt.Errorf("error in reading file %s: %s\n", key, err)
        }

        reader := csv.NewReader(body)
        record, err := reader.ReadAll()
        if err != nil {
            fmt.Println("Error", err)
        }

        for value := range record { // for i:=0; i<len(record)
            fmt.Println("", record[value])
        }
    }
    return nil
}

Я пытаюсь разобрать файл CSV с S3, что-то сделать с каждой строкой, но я получаю

cannot use body (type []byte) as type io.Reader in argument to csv.NewReader:
    []byte does not implement io.Reader (missing Read method)

Любой советвысоко ценится

1 Ответ

0 голосов
/ 28 сентября 2018

Как говорит ошибка:

не может использовать тело (тип [] байт) в качестве типа io.Reader в аргументе csv.NewReader: [] байт не реализует io.Reader (отсутствует чтениеметод)

, поскольку вы передаете []byte, возвращенный из ответа на csv.NewReader

Требуется реализовать io.Reader для тела, чтобы передать его в качестве аргумента csv.NewReader.Так как он принимает io.Reader в качестве аргумента.Попробуйте изменить свой код следующим образом:

reader := csv.NewReader(bytes.NewBuffer(body))
record, err := reader.ReadAll()
if err != nil {
    fmt.Println("Error", err)
}

Также, поскольку aws.GetObject возвращает указатель на GetObjectOutput struct.

func (c *S3) GetObject(input *GetObjectInput) (*GetObjectOutput, error)

, которая сама реализует Reader

type GetObjectOutput struct {
    ....
    // Object data.
    Body io.ReadCloser `type:"blob"`
    ....
}

, так что вы можете передать возвращенное тело непосредственно в csv.NewReader.

Еще одна вещь, которую вы можете использовать для загрузкиManager

Загрузчик пакета s3manager обеспечивает одновременную загрузку объектов из S3.Загрузчик запишет содержимое объекта S3 с помощью io.WriterAt.После создания экземпляра Downloader вы можете безопасно вызывать Download одновременно из нескольких групп.

func (d Downloader) Download(w io.WriterAt, input *s3.GetObjectInput, options ...func(*Downloader)) (n int64, err error)

Download загружает объект в S3 и записывает полезную нагрузку в w с помощью одновременных запросов GET.

Безопасно вызывать этот метод одновременно через goroutines.

// The session the S3 Downloader will use
sess := session.Must(session.NewSession())

// Create a downloader with the session and default options
downloader := s3manager.NewDownloader(sess)

// Create a file to write the S3 Object contents to.
f, err := os.Create(filename)
if err != nil {
    return fmt.Errorf("failed to create file %q, %v", filename, err)
}

// Write the contents of S3 Object to the file
n, err := downloader.Download(f, &s3.GetObjectInput{
    Bucket: aws.String(myBucket),
    Key:    aws.String(myString),
})
if err != nil {
    return fmt.Errorf("failed to download file, %v", err)
}
...