Skip to content

Instantly share code, notes, and snippets.

@feltnerm
Created July 29, 2014 22:02
Show Gist options
  • Save feltnerm/31947822af77b71b6ccd to your computer and use it in GitHub Desktop.
Save feltnerm/31947822af77b71b6ccd to your computer and use it in GitHub Desktop.
go fineuploader server (work in-progress)
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