Last active
May 23, 2023 04:25
-
-
Save ezr/392fc583346712eb5bb90b8ee5f38227 to your computer and use it in GitHub Desktop.
HTTP server to accept file uploads
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
package main | |
/* Taken from https://github.com/TannerGabriel/learning-go/tree/master/beginner-programs/FileUpload with some tweaks | |
*/ | |
import ( | |
"flag" | |
"fmt" | |
"html/template" | |
"io" | |
"net" | |
"net/http" | |
"os" | |
"strings" | |
) | |
// Compile templates on start of the application | |
var tmpl, _ = template.New("upload").Parse(`<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>Upload File</title> | |
<style> | |
body { | |
background-color: #3b3b3b; | |
color: #eeeeee; | |
font-size: 1.5em; | |
font-family: sans-serif; | |
} | |
</style> | |
</head> | |
<body> | |
<form | |
enctype="multipart/form-data" | |
action="http://{{.Host}}/" | |
method="post" | |
> | |
<input type="file" name="myFile" /> | |
<input type="submit" value="upload" /> | |
</form> | |
<p>{{.Message}}<i>{{.Filename}}</i></p> | |
<br> | |
<p>curl upload: <code>curl -F myFile=@FileName http://{{.Host}}/</code></p> | |
</body> | |
</html>`) | |
type pageData struct { | |
Host string | |
Message string | |
Filename string | |
} | |
func uploadFile(w http.ResponseWriter, r *http.Request) { | |
// Maximum upload of 10 MB files | |
r.ParseMultipartForm(10 << 20) | |
// Get handler for filename, size and headers | |
file, handler, err := r.FormFile("myFile") | |
if err != nil { | |
fmt.Println("Error Retrieving the File") | |
fmt.Println(err) | |
display(w, r, "Error retrieving the file. Upload failed.", "") | |
return | |
} | |
defer file.Close() | |
fmt.Printf("Uploaded File: %+v\n", handler.Filename) | |
fmt.Printf("File Size: %+v\n", byteCountIEC(handler.Size)) | |
fmt.Printf("MIME Header: %+v\n", handler.Header) | |
// Create file | |
dst, err := os.Create(handler.Filename) | |
defer dst.Close() | |
if err != nil { | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
// Copy the uploaded file to the created file on the filesystem | |
if _, err := io.Copy(dst, file); err != nil { | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
display(w, r, "Successfully Uploaded File ", handler.Filename) | |
} | |
func display(w http.ResponseWriter, r *http.Request, m, fname string) { | |
page := pageData{ | |
Host: r.Host, | |
Message: m, | |
Filename: fname, | |
} | |
tmpl.Execute(w, page) | |
} | |
func uploadHandler(w http.ResponseWriter, r *http.Request) { | |
switch r.Method { | |
case "GET": | |
display(w, r, "", "") | |
case "POST": | |
uploadFile(w, r) | |
} | |
} | |
// function from https://yourbasic.org/golang/byte-count.go | |
func byteCountIEC(b int64) string { | |
const unit = 1024 | |
if b < unit { | |
return fmt.Sprintf("%d B", b) | |
} | |
div, exp := int64(unit), 0 | |
for n := b / unit; n >= unit; n /= unit { | |
div *= unit | |
exp++ | |
} | |
return fmt.Sprintf("%.1f %ciB", | |
float64(b)/float64(div), "KMGTPE"[exp]) | |
} | |
func printIPAddrs() { | |
ifaces, err := net.Interfaces() | |
if err != nil { | |
// this function isn't critical, let's just give up | |
return | |
} | |
for _, intf := range ifaces { | |
addrs, err := intf.Addrs() | |
if err != nil { | |
return | |
} | |
if strings.Contains(intf.Flags.String(), "up") { | |
for _, addr := range addrs { | |
fmt.Printf(" %s\n", strings.Split(addr.String(), "/")[0]) | |
} | |
} | |
} | |
} | |
func main() { | |
port := flag.String("port", "9090", "port to serve on") | |
addr := flag.String("addr", "", "address to serve from (defaults to all interfaces)") | |
flag.Usage = func() { | |
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) | |
flag.PrintDefaults() | |
fmt.Fprintf(os.Stderr, "\nUploading file foo with curl:\n") | |
fmt.Fprintf(os.Stderr, " $ curl -F myFile=@foo http://<ip>:<port>/\n") | |
} | |
flag.Parse() | |
http.HandleFunc("/", uploadHandler) | |
listenSocket := fmt.Sprintf("%s:%s", *addr, *port) | |
fmt.Println("[*] listening on", listenSocket) | |
if *addr == "" { | |
fmt.Println("[*] current addresses:") | |
printIPAddrs() | |
} | |
http.ListenAndServe(listenSocket, nil) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Upload a file with curl:
curl -F myFile=@FileName http://127.0.0.1:9090/