lambda multipart/file 在 go 中上传
lambda multipart/file upload in go
我需要使用 Go 对通过 AWS Lambda 上传的上传文件的内容进行一些简单的操作,但不确定如何解析接收的内容,因为我是 Go 的新手。到目前为止我找到的解决方案与http包和MultiPart表单功能有关。
type Request events.APIGatewayProxyRequest
func Handler(ctx context.Context, req Request) (Response, error) {
fmt.Println(req.Body)
....
}
这是我的请求正文的样子
------WebKitFormBoundaryx0SVDelfa90Fi5Uo
Content-Disposition: form-data; name="file"; filename="upload.txt"
Content-Type: text/plain
this is content
------WebKitFormBoundaryx0SVDelfa90Fi5Uo--
我的请求是 APIGatewayProxyRequest
的实例。
我想知道是否有可能获得一个自定义结构,我可以从中访问数据,例如 f.e。
customStruct.content => "this is content"
customStruct.fileName => upload.txt
customStruct.fileExtension => txt
这个有 3 个部分:
- 从
events.APIGatewayProxyRequest
创建一个 multipart.Reader
- 获取 MIME 部分
- 提取 MIME 部件值
第 1 步:创建 multipart.Reader
multipart.NewReader
采用 io.Reader
和 boundary
字符串,如签名所示:
func NewReader(r io.Reader, boundary string) *Reader
为此,您需要从 Content-Type
HTTP 请求 header 中提取边界字符串,这可以使用 mime.ParseMediaType
.
来完成
一个简单的方法是从具有以下签名的 go-awslambda
包中调用 NewReaderMultipart
:
func NewReaderMultipart(req events.APIGatewayProxyRequest) (*multipart.Reader, error)
第 2 步:获取 MIME 部分
获得 mime.Reader
后,浏览 MIME 消息,直到找到所需的 MIME 部分。
这里的例子只有一个部分,所以你可以直接调用:
part, err := reader.NextPart()
第 3 步:提取 MIME 部分值
获得 MIME 部分后,即可提取所需的值。
步骤 3.1:内容
content, err := io.ReadAll(part)
步骤 3.2:文件名
从MIME部分获取文件名如下:
filename := part.FileName()
步骤 3.3:文件扩展名
呼叫path/filepath.Ext
。这将在扩展中添加前导句点 .
,但这可以很容易地删除。
ext := filepath.Ext(part.FileName())
总结
您可以按如下方式组合:
import (
"context"
"encoding/json"
"io"
"github.com/aws/aws-lambda-go/events"
"github.com/grokify/go-awslambda"
)
type customStruct struct {
Content string
FileName string
FileExtension string
}
func handleRequest(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
res := events.APIGatewayProxyResponse{}
r, err := awslambda.NewReaderMultipart(req)
if err != nil {
return res, err
}
part, err := r.NextPart()
if err != nil {
return res, err
}
content, err := io.ReadAll(part)
if err != nil {
return res, err
}
custom := customStruct{
Content: string(content),
FileName: part.FileName(),
FileExtension: filepath.Ext(part.FileName())}
customBytes, err := json.Marshal(custom)
if err != nil {
return res, err
}
res = events.APIGatewayProxyResponse{
StatusCode: 200,
Headers: map[string]string{
"Content-Type": "application/json"},
Body: string(customBytes)}
return res, nil
}
上面的答案看起来是 正确的 方法,但是如果你很懒惰(就像我一样 :p )你可以创建一个 HTTP 请求,然后让本机库适合您:
httpReq, err := http.NewRequestWithContext(ctx, req.HTTPMethod, reqURL.String(), strings.NewReader(req.Body))
if err != nil {
return nil, errors.New("failed to convert a lambda req into a http req")
}
// some headers may be important, let get all of them, just in case
for name, value := range req.Headers {
httpReq.Header.Add(name, value)
}
// from here you can use httpReq.FormFile() to read the file
我需要使用 Go 对通过 AWS Lambda 上传的上传文件的内容进行一些简单的操作,但不确定如何解析接收的内容,因为我是 Go 的新手。到目前为止我找到的解决方案与http包和MultiPart表单功能有关。
type Request events.APIGatewayProxyRequest
func Handler(ctx context.Context, req Request) (Response, error) {
fmt.Println(req.Body)
....
}
这是我的请求正文的样子
------WebKitFormBoundaryx0SVDelfa90Fi5Uo
Content-Disposition: form-data; name="file"; filename="upload.txt"
Content-Type: text/plain
this is content
------WebKitFormBoundaryx0SVDelfa90Fi5Uo--
我的请求是 APIGatewayProxyRequest
的实例。
我想知道是否有可能获得一个自定义结构,我可以从中访问数据,例如 f.e。
customStruct.content => "this is content"
customStruct.fileName => upload.txt
customStruct.fileExtension => txt
这个有 3 个部分:
- 从
events.APIGatewayProxyRequest
创建一个 - 获取 MIME 部分
- 提取 MIME 部件值
multipart.Reader
第 1 步:创建 multipart.Reader
multipart.NewReader
采用 io.Reader
和 boundary
字符串,如签名所示:
func NewReader(r io.Reader, boundary string) *Reader
为此,您需要从 Content-Type
HTTP 请求 header 中提取边界字符串,这可以使用 mime.ParseMediaType
.
一个简单的方法是从具有以下签名的 go-awslambda
包中调用 NewReaderMultipart
:
func NewReaderMultipart(req events.APIGatewayProxyRequest) (*multipart.Reader, error)
第 2 步:获取 MIME 部分
获得 mime.Reader
后,浏览 MIME 消息,直到找到所需的 MIME 部分。
这里的例子只有一个部分,所以你可以直接调用:
part, err := reader.NextPart()
第 3 步:提取 MIME 部分值
获得 MIME 部分后,即可提取所需的值。
步骤 3.1:内容
content, err := io.ReadAll(part)
步骤 3.2:文件名
从MIME部分获取文件名如下:
filename := part.FileName()
步骤 3.3:文件扩展名
呼叫path/filepath.Ext
。这将在扩展中添加前导句点 .
,但这可以很容易地删除。
ext := filepath.Ext(part.FileName())
总结
您可以按如下方式组合:
import (
"context"
"encoding/json"
"io"
"github.com/aws/aws-lambda-go/events"
"github.com/grokify/go-awslambda"
)
type customStruct struct {
Content string
FileName string
FileExtension string
}
func handleRequest(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
res := events.APIGatewayProxyResponse{}
r, err := awslambda.NewReaderMultipart(req)
if err != nil {
return res, err
}
part, err := r.NextPart()
if err != nil {
return res, err
}
content, err := io.ReadAll(part)
if err != nil {
return res, err
}
custom := customStruct{
Content: string(content),
FileName: part.FileName(),
FileExtension: filepath.Ext(part.FileName())}
customBytes, err := json.Marshal(custom)
if err != nil {
return res, err
}
res = events.APIGatewayProxyResponse{
StatusCode: 200,
Headers: map[string]string{
"Content-Type": "application/json"},
Body: string(customBytes)}
return res, nil
}
上面的答案看起来是 正确的 方法,但是如果你很懒惰(就像我一样 :p )你可以创建一个 HTTP 请求,然后让本机库适合您:
httpReq, err := http.NewRequestWithContext(ctx, req.HTTPMethod, reqURL.String(), strings.NewReader(req.Body))
if err != nil {
return nil, errors.New("failed to convert a lambda req into a http req")
}
// some headers may be important, let get all of them, just in case
for name, value := range req.Headers {
httpReq.Header.Add(name, value)
}
// from here you can use httpReq.FormFile() to read the file