Created
March 25, 2024 17:51
-
-
Save aryomuzakki/6e0d6c38081709c536e6ed97f0d16fdc to your computer and use it in GitHub Desktop.
Example to handle image upload in go lang (with gorilla mux router). Save image as temp files, remove image, return image / serve image as response
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Handle image uploaded with multipart/form-data POST Request. | |
Save image to temp files, | |
image then removed after some process, | |
then return / serve the (processed) image as response. | |
Using gorilla mux router. | |
*/ | |
package main | |
import ( | |
"fmt" | |
"io" | |
"net/http" | |
"path/filepath" | |
"runtime" | |
"strings" | |
) | |
type ImageFile struct { | |
Name string | |
FullPath string | |
MimeType string | |
Bytes []byte | |
} | |
var ( | |
_, b, _, _ = runtime.Caller(0) | |
RootPath = filepath.Join(filepath.Dir(b), "../") | |
tempFolderPath = filepath.Join(RootPath, "/temp-files") | |
) | |
func uploadHandler(w http.ResponseWriter, r *http.Request) { | |
// max total size 20mb | |
r.ParseMultipartForm(200 << 20) | |
f, h, err := r.FormFile("image") | |
if err != nil { | |
fmt.Printf("Error reading file of 'image' form data. Reason: %s\n", err) | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
sourceImg, err := saveFile(f, h) | |
if err != nil { | |
fmt.Printf("Error saving file. Reason: %s\n", err) | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
// some processing here | |
removeFile(sourceImg.FullPath) | |
w.Header().Set("Content-Type", sourceImg.MimeType) | |
w.Header().Set("Content-Disposition", `inline; filename="`+removedExt(sourceImg.Name)+`.jpg"`) | |
w.Write(sourceImg.Bytes) | |
} | |
func removedExt(f string) string { | |
return strings.TrimSuffix(f, filepath.Ext(f)) | |
} | |
func saveFile(f multipart.File, h *multipart.FileHeader) (ImageFile, error) { | |
defer f.Close() | |
tempFileName := fmt.Sprintf("uploaded-%s-*%s", removedExt(h.Filename), filepath.Ext(h.Filename)) | |
tempFile, err := os.CreateTemp(tempFolderPath, tempFileName) | |
if err != nil { | |
errStr := fmt.Sprintf("Error in creating the file. Reason: %s\n", err) | |
fmt.Println(errStr) | |
return ImageFile{}, err | |
} | |
defer tempFile.Close() | |
filebytes, err := io.ReadAll(f) | |
if err != nil { | |
errStr := fmt.Sprintf("Error in reading the file buffer. Reason: %s\n", err) | |
fmt.Println(errStr) | |
return ImageFile{}, err | |
} | |
tempFile.Write(filebytes) | |
_, tFilename := filepath.Split(tempFile.Name()) | |
imgFile := ImageFile{ | |
Name: tFilename, | |
FullPath: tempFile.Name(), | |
MimeType: h.Header.Get("Content-Type"), | |
Bytes: filebytes, | |
} | |
return imgFile, nil | |
} | |
func removeFile(p string) bool { | |
err := os.Remove(p) | |
if err != nil { | |
fmt.Printf("\nCannot remove file. Reason: %s\n", err) | |
return false | |
} | |
return true | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Steps | |
1. In a new project folder, run `go mod init projectName`. | |
2. Add gorilla mux package by running `go get github.com/gorilla/mux`. | |
2. Copy 'main.go' and 'uploadHandler.go' to your folder. | |
3. Run `go run main.go` or with specified port from terminal `go run main.go --addr :5050` | |
*/ | |
package main | |
import ( | |
"flag" | |
"fmt" | |
"log" | |
"net/http" | |
"github.com/gorilla/mux" | |
) | |
func main() { | |
addr := flag.String("addr", ":5000", "server port") | |
flag.Parse() | |
r := mux.NewRouter() | |
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | |
w.Write([]byte("{\"message\": \"hello world\"}")) | |
}).Methods(http.MethodGet) | |
r.HandleFunc("/upload", uploadHandler).Methods(http.MethodPost) | |
fmt.Printf("server run on %s\n", *addr) | |
log.Fatal(http.ListenAndServe(*addr, r)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment