Created
July 29, 2014 22:02
-
-
Save feltnerm/31947822af77b71b6ccd to your computer and use it in GitHub Desktop.
go fineuploader server (work in-progress)
This file contains hidden or 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 | |
import ( | |
"fmt" | |
"io" | |
"log" | |
"mime/multipart" | |
"net/http" | |
"net/http/httputil" | |
"os" | |
"path" | |
"strconv" | |
"time" | |
) | |
var FineUploaderParams = map[string]string{ | |
"file": "qqfile", | |
"name": "qqfilename", | |
"uuid": "qquuid", | |
"totalSize": "qqtotalfilesize", | |
"chunkIndex": "qqpartindex", | |
"chunkSize": "qqchunksize", | |
"totalChunks": "qqtotalparts", | |
} | |
var RootUploadDirectory = "/tmp/uploads" | |
var UploadDirectory = path.Join(RootUploadDirectory, "uploads") | |
var ChunksDirectory = path.Join(RootUploadDirectory, "chunks") | |
type UploadedFile struct { | |
File multipart.File | |
TotalSize int64 | |
Uuid string | |
Name string | |
} | |
type ChunkedUploadedFile struct { | |
ChunkIndex int | |
ChunkSize int | |
TotalChunks int | |
UploadedFile UploadedFile | |
} | |
func uploadHandler(l *log.Logger) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
var method = r.Method | |
switch { | |
case method == "POST": | |
l.Println("POST") | |
l.Println("upload received") | |
file, _, err := r.FormFile(FineUploaderParams["file"]) | |
if err != nil { | |
http.Error(w, err.Error(), 500) | |
return | |
} | |
var uuid = r.FormValue(FineUploaderParams["uuid"]) | |
var name = r.FormValue(FineUploaderParams["name"]) | |
totalSize, err := strconv.ParseInt(r.FormValue(FineUploaderParams["totalSize"]), 10, 64) | |
if err != nil { | |
http.Error(w, err.Error(), 500) | |
return | |
} | |
uploadedFile := &UploadedFile{ | |
File: file, | |
Uuid: uuid, | |
Name: name, | |
TotalSize: totalSize, | |
} | |
l.Println(uploadedFile.Name) | |
l.Println(uploadedFile.Uuid) | |
totalChunks, err := strconv.Atoi(r.FormValue(FineUploaderParams["totalChunks"])) | |
if err != nil { | |
http.Error(w, err.Error(), 500) | |
return | |
} | |
if totalChunks > 1 { | |
// @TODO: ensure numbers for size and such are within expected range | |
l.Println("chunked upload") | |
chunkedIndex, _ := strconv.Atoi(r.FormValue(FineUploaderParams["chunkIndex"])) | |
chunkSize, _ := strconv.Atoi(r.FormValue(FineUploaderParams["chunkSize"])) | |
//totalChunks, _ := strconv.Atoi(r.FormValue(FineUploaderParams["totalChunks"])) | |
chunkedUploadedFile := &ChunkedUploadedFile{ | |
ChunkIndex: chunkedIndex, | |
ChunkSize: chunkSize, | |
TotalChunks: totalChunks, | |
UploadedFile: *uploadedFile, | |
} | |
l.Println(chunkedUploadedFile.ChunkIndex) | |
l.Println(chunkedUploadedFile.TotalChunks) | |
} else { | |
l.Println("non-chunked upload") | |
// @TODO: add some checks before just creating random file | |
// systems and/or just leave it all to the user | |
fileDir := path.Join(UploadDirectory, uploadedFile.Uuid) | |
err = os.MkdirAll(fileDir, 0777) | |
if err != nil { | |
http.Error(w, err.Error(), 500) | |
} | |
filePath := path.Join(fileDir, uploadedFile.Name) | |
dst, err := os.Create(filePath) | |
defer dst.Close() | |
if err != nil { | |
http.Error(w, err.Error(), 500) | |
} | |
if _, err := io.Copy(dst, uploadedFile.File); err != nil { | |
http.Error(w, err.Error(), 500) | |
} | |
} | |
case method == "DELETE": | |
l.Println("DELETE") | |
} | |
fmt.Fprintf(w, "hi!\n") | |
return | |
}) | |
} | |
func logRequest(l *log.Logger, next http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
dump, err := httputil.DumpRequest(r, false) | |
s := string(dump[:]) | |
if err != nil { | |
l.Println(err) | |
} else { | |
l.Println(s) | |
} | |
next.ServeHTTP(w, r) | |
}) | |
} | |
func withMetrics(l *log.Logger, next http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
began := time.Now() | |
next.ServeHTTP(w, r) | |
l.Printf("%s %s took %s", r.Method, r.URL, time.Since(began)) | |
}) | |
} | |
func main() { | |
logger := log.New(os.Stdout, "", 0) | |
// host static files | |
http.Handle("/", http.FileServer(http.Dir("./static"))) | |
// handle the root | |
http.Handle("/upload", withMetrics(logger, logRequest(logger, uploadHandler(logger)))) | |
logger.Println("Go go gadget server!") | |
http.ListenAndServe(":8080", nil) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment