khi*_*ter 1 csv amazon-s3 go aws-lambda
我有以下代码:
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
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试从 S3 解析 CSV 文件,对每一行做一些事情,但我得到了
cannot use body (type []byte) as type io.Reader in argument to csv.NewReader:
[]byte does not implement io.Reader (missing Read method)
Run Code Online (Sandbox Code Playgroud)
非常感谢任何建议
正如错误所说:
不能在 csv.NewReader 的参数中使用 body(类型 []byte)作为类型 io.Reader:[]byte 没有实现 io.Reader(缺少 Read 方法)
因为你[]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)
}
Run Code Online (Sandbox Code Playgroud)
也因为aws.GetObject返回指向GetObjectOutput结构的指针。
func (c *S3) GetObject(input *GetObjectInput) (*GetObjectOutput, error)
Run Code Online (Sandbox Code Playgroud)
它本身实现了 Reader
type GetObjectOutput struct {
....
// Object data.
Body io.ReadCloser `type:"blob"`
....
}
Run Code Online (Sandbox Code Playgroud)
因此您可以将返回的正文直接传递给 csv.NewReader。
还有一件事是你可以去下载管理器
s3manager 包的下载器提供从 S3 并发下载对象。下载器将使用 io.WriterAt 写入 S3 对象内容。创建 Downloader 实例后,您可以安全地从多个 goroutine 并发调用 Download。
func (d Downloader) Download(w io.WriterAt, input *s3.GetObjectInput, options ...func(*Downloader)) (n int64, err error)
Run Code Online (Sandbox Code Playgroud)
Download 在 S3 中下载一个对象,并使用并发 GET 请求将有效负载写入 w。
跨 goroutine 并发调用此方法是安全的。
// 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)
}
Run Code Online (Sandbox Code Playgroud)