From 520a74c736aa423c5d4fa90c3c58f3dd55afd7df Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sat, 17 Mar 2018 21:48:36 +0100
Subject: [PATCH] Allow multiple uploads

---
 main.go               | 133 +++++++++++++++++++++++++++---------------
 templates/upload.html |  26 ++++-----
 types.go              |   2 +-
 3 files changed, 99 insertions(+), 62 deletions(-)

diff --git a/main.go b/main.go
index 101eeb1..71d935d 100644
--- a/main.go
+++ b/main.go
@@ -91,8 +91,8 @@ func parseUser(r *http.Request) UserInfo {
 }
 
 type UploadData struct {
-	User   UserInfo
-	Result Result
+	User    UserInfo
+	Results []Result
 }
 
 func returnResult(w http.ResponseWriter, templateName string, data interface{}) error {
@@ -129,59 +129,95 @@ func main() {
 		if r.Method == "POST" {
 			user := parseUser(r)
 
-			r.ParseMultipartForm(32 << 20)
-			file, header, err := r.FormFile("file")
-			image, err := createImage(&config, file, header)
+			err := r.ParseMultipartForm(32 << 20)
 			if err != nil {
-				returnResult(w, "upload.html", UploadData{
+				if err = returnResult(w, "upload.html", UploadData{
 					user,
-					Result{
-						Id:      "",
+					[]Result{{
 						Success: false,
 						Errors:  []string{err.Error()},
-					},
-				})
-				return
+					}},
+				}); err != nil {
+					panic(err)
+				}
 			}
 
-			_, err = db.Exec("INSERT INTO images (id, owner, created_at, original_name, type) VALUES ($1, $2, $3, $4, $5)", image.Id, user.Id, image.CreatedAt, image.OriginalName, image.MimeType)
-			if err != nil {
-				panic(err)
+			var images []Image
+			var ids []string
+
+			m := r.MultipartForm
+			files := m.File["file"]
+			for _, header := range files {
+				file, err := header.Open()
+				if err != nil {
+					if err = returnResult(w, "upload.html", UploadData{
+						user,
+						[]Result{{
+							Success: false,
+							Errors:  []string{err.Error()},
+						}},
+					}); err != nil {
+						panic(err)
+					}
+					return
+				}
+				image, err := createImage(&config, file, header)
+				if err != nil {
+					if err = returnResult(w, "upload.html", UploadData{
+						user,
+						[]Result{{
+							Success: false,
+							Errors:  []string{err.Error()},
+						}},
+					}); err != nil {
+						panic(err)
+					}
+					return
+				}
+
+				images = append(images, image)
+				ids = append(ids, image.Id)
 			}
 
-			fmt.Printf("Created task %s at %d\n", image.Id, time.Now().Unix())
+			pubsub := client.Subscribe(config.ResultChannel)
 
-			data, err := json.Marshal(image)
-			if err != nil {
-				if err = returnResult(w, "upload.html", UploadData{
-					user,
-					Result{
-						Id:      image.Id,
-						Success: false,
-						Errors:  []string{err.Error()},
-					},
-				}); err != nil {
+			for _, image := range images {
+				_, err = db.Exec("INSERT INTO images (id, owner, created_at, original_name, type) VALUES ($1, $2, $3, $4, $5)", image.Id, user.Id, image.CreatedAt, image.OriginalName, image.MimeType)
+				if err != nil {
 					panic(err)
 				}
-				return
-			}
 
-			pubsub := client.Subscribe(config.ResultChannel)
-			client.RPush(fmt.Sprintf("queue:%s", config.ImageQueue), data)
+				data, err := json.Marshal(images)
+				if err != nil {
+					if err = returnResult(w, "upload.html", UploadData{
+						user,
+						[]Result{{
+							Success: false,
+							Errors:  []string{err.Error()},
+						}},
+					}); err != nil {
+						panic(err)
+					}
+					return
+				}
+
+				fmt.Printf("Created task %s at %d\n", image.Id, time.Now().Unix())
+				client.RPush(fmt.Sprintf("queue:%s", config.ImageQueue), data)
+				fmt.Printf("Submitted task %s at %d\n", image.Id, time.Now().Unix())
+			}
 
-			fmt.Printf("Submitted task %s at %d\n", image.Id, time.Now().Unix())
+			var results []Result
 
-			waiting := true
-			for waiting {
+			var waiting map[string]bool
+			for len(waiting) != 0 {
 				message, err := pubsub.ReceiveMessage()
 				if err != nil {
 					if err = returnResult(w, "upload.html", UploadData{
 						user,
-						Result{
-							Id:      image.Id,
+						[]Result{{
 							Success: false,
 							Errors:  []string{err.Error()},
-						},
+						}},
 					}); err != nil {
 						panic(err)
 					}
@@ -193,11 +229,10 @@ func main() {
 				if err != nil {
 					if err = returnResult(w, "upload.html", UploadData{
 						user,
-						Result{
-							Id:      image.Id,
+						[]Result{{
 							Success: false,
 							Errors:  []string{err.Error()},
-						},
+						}},
 					}); err != nil {
 						panic(err)
 					}
@@ -206,23 +241,25 @@ func main() {
 
 				fmt.Printf("Returned task %s at %d\n", result.Id, time.Now().Unix())
 
-				if result.Id == image.Id {
-					waiting = false
+				if _, ok := waiting[result.Id]; ok {
+					delete(waiting, result.Id)
 
-					if err = returnResult(w, "upload.html", UploadData{
-						user,
-						result,
-					}); err != nil {
-						panic(err)
-					}
-					return
+					results = append(results, result)
 				}
 			}
+
+			if err = returnResult(w, "upload.html", UploadData{
+				user,
+				results,
+			}); err != nil {
+				panic(err)
+			}
+			return
 		} else {
 			user := parseUser(r)
 			if err = returnResult(w, "upload.html", UploadData{
 				user,
-				Result{},
+				[]Result{},
 			}); err != nil {
 				panic(err)
 			}
diff --git a/templates/upload.html b/templates/upload.html
index 08b68c3..3663ee5 100644
--- a/templates/upload.html
+++ b/templates/upload.html
@@ -11,19 +11,19 @@
     <a href="/upload">Upload</a>
 </p>
 
-{{ if .Result.Id }}
-    {{ if .Result.Success }}
-        <div class="info success">
-            <h2>Upload of {{ .Result.Id }} finished. <a href="/i/{{ .Result.Id }}">View</a>.</h2>
-        </div>
-    {{ else }}
-        <div class="info error">
-            <h2>Upload of {{ .Result.Id }} failed.</h2>
-            {{ range .Result.Errors }}
-                <pre>{{ . }}</pre>
-            {{ end }}
-        </div>
-    {{ end }}
+{{ range .Results }}
+{{ if .Success }}
+<div class="info success">
+    <h2>Upload of {{ .Id }} finished. <a href="/i/{{ .Id }}">View</a>.</h2>
+</div>
+{{ else }}
+<div class="info error">
+    <h2>Upload of {{ .Id }} failed.</h2>
+{{ range .Errors }}
+    <pre>{{ . }}</pre>
+{{ end }}
+</div>
+{{ end }}
 {{ end }}
 
 <form action="/upload/" method="POST" enctype="multipart/form-data">
diff --git a/types.go b/types.go
index 2ea713f..ddd6a21 100644
--- a/types.go
+++ b/types.go
@@ -16,7 +16,7 @@ type Image struct {
 }
 
 type Result struct {
-	Id      string   `json:"id"`
+	Id      string `json:"id"`
 	Success bool     `json:"success"`
 	Errors  []string `json:"errors"`
 }
-- 
GitLab