前置作業
先到 AWS IAM 建立一個使用者,打開「Security credentials」頁籤,並選擇「Create access key」按鈕,最後將生成的「Access key ID」和「Secret access key」儲存起來。
實作
建立專案。
| 12
 
 | mkdir go-s3-examplecd go-s3-example
 
 | 
初始化 Go Modules。
| 1
 | go mod init github.com/memochou1993/go-s3-example
 | 
下載 aws-sdk-go 套件。
| 1
 | go get github.com/aws/aws-sdk-go/aws
 | 
新增 main.go 檔,填入必要變數。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 
 | var (AccessKeyID     = ""
 SecretAccessKey = ""
 Region          = ""
 Bucket          = ""
 )
 
 func main() {
 
 sess := ConnectAws()
 
 
 http.Handle("/", http.FileServer(http.Dir("./public")))
 
 
 http.HandleFunc("/upload-file", func(w http.ResponseWriter, r *http.Request) {
 r.ParseMultipartForm(32 << 20)
 for _, fileHeaders := range r.MultipartForm.File {
 for _, header := range fileHeaders {
 Upload(sess, Bucket, header)
 }
 }
 })
 
 
 http.HandleFunc("/upload-files", func(w http.ResponseWriter, r *http.Request) {
 r.ParseMultipartForm(32 << 20)
 for _, fileHeaders := range r.MultipartForm.File {
 UploadMultiple(sess, Bucket, fileHeaders)
 }
 })
 
 log.Fatal(http.ListenAndServe(":8080", nil))
 }
 
 | 
新增 ConnectAws 方法,用來取得一個 Session:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | func ConnectAws() *session.Session {
 sess, err := session.NewSession(&aws.Config{
 Region: aws.String(Region),
 Credentials: credentials.NewStaticCredentials(
 AccessKeyID,
 SecretAccessKey,
 "",
 ),
 })
 if err != nil {
 panic(err)
 }
 return sess
 }
 
 | 
新增 Upload 方法,用來上傳單一檔案:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | func Upload(sess *session.Session, bucket string, header *multipart.FileHeader) error {svc := s3manager.NewUploader(sess)
 src, err := header.Open()
 if err != nil {
 return err
 }
 if _, err := svc.Upload(&s3manager.UploadInput{
 Bucket: aws.String(bucket),
 ACL:    aws.String("public-read"),
 Key:    aws.String(header.Filename),
 Body:   src,
 }); err != nil {
 return err
 }
 return nil
 }
 
 | 
新增 UploadMultiple 方法,用來上傳多個檔案:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | func UploadMultiple(sess *session.Session, bucket string, fileHeaders []*multipart.FileHeader) error {var objects []s3manager.BatchUploadObject
 for _, header := range fileHeaders {
 src, err := header.Open()
 if err != nil {
 return err
 }
 objects = append(objects, s3manager.BatchUploadObject{
 Object: &s3manager.UploadInput{
 Bucket: aws.String(bucket),
 ACL:    aws.String("public-read"),
 Key:    aws.String(header.Filename),
 Body:   src,
 },
 })
 }
 svc := s3manager.NewUploader(sess)
 iter := &s3manager.UploadObjectsIterator{Objects: objects}
 return svc.UploadWithIterator(aws.BackgroundContext(), iter)
 }
 
 | 
在 public 資料夾新增 index.html 檔,當作表單:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | <!DOCTYPE html><html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 </head>
 <body>
 
 <form method="POST" action="/upload-file" enctype="multipart/form-data">
 <input type="file" name="files[]">
 <input type="submit">
 </form>
 
 <form method="POST" action="/upload-files" enctype="multipart/form-data">
 <input type="file" name="files[]" multiple>
 <input type="submit">
 </form>
 </body>
 </html>
 
 | 
執行。
前端
使用 Axios 上傳檔案,範例如下。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 
 | <!DOCTYPE html><html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
 </head>
 <body id="app">
 <input id="file" type="file">
 <button onclick="upload()">Upload</button>
 <script>
 const upload = async () => {
 const file = document.getElementById('file').files[0];
 const formData = new FormData();
 formData.append('files[]', file);
 const res = await axios('https://localhost:8080/upload-file', {
 method: 'POST',
 headers: {
 'Content-Type': 'multipart/form-data',
 },
 data: formData,
 });
 console.log(res);
 const img = document.createElement('img');
 img.setAttribute('src', `${res.data.data.avatar}?t=${+new Date()}`);
 document.getElementById('app').appendChild(img);
 };
 </script>
 </body>
 </html>
 
 | 
瀏覽網頁
前往 http://127.0.0.1:8080 瀏覽。
參考資料