mirror of https://github.com/perkeep/perkeep.git
126 lines
2.4 KiB
Go
126 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"http"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
)
|
|
|
|
// For `make`:
|
|
//import "./util/_obj/util"
|
|
// For `gofr`:
|
|
import "util/util"
|
|
|
|
func handleMultiPartUpload(conn *http.Conn, req *http.Request) {
|
|
if !(req.Method == "POST" && req.URL.Path == "/camli/upload") {
|
|
badRequestError(conn, "Inconfigured handler.")
|
|
return
|
|
}
|
|
|
|
multipart, err := req.MultipartReader()
|
|
if multipart == nil {
|
|
badRequestError(conn, fmt.Sprintf(
|
|
"Expected multipart/form-data POST request; %v", err))
|
|
return
|
|
}
|
|
|
|
for {
|
|
part, err := multipart.NextPart()
|
|
if err != nil {
|
|
fmt.Println("Error reading multipart section:", err)
|
|
break
|
|
}
|
|
if part == nil {
|
|
break
|
|
}
|
|
formName := part.FormName()
|
|
fmt.Printf("New value [%s], part=%v\n", formName, part)
|
|
|
|
ref := ParseBlobRef(formName)
|
|
if ref == nil {
|
|
fmt.Printf("Ignoring form key [%s]\n", formName)
|
|
continue
|
|
}
|
|
|
|
ok, err := receiveBlob(ref, part)
|
|
if !ok {
|
|
fmt.Printf("Error receiving blob %v: %v\n", ref, err)
|
|
} else {
|
|
fmt.Printf("Received blob %v\n", ref)
|
|
}
|
|
}
|
|
fmt.Println("Done reading multipart body.")
|
|
}
|
|
|
|
func receiveBlob(blobRef *BlobRef, source io.Reader) (ok bool, err os.Error) {
|
|
hashedDirectory := blobRef.DirectoryName()
|
|
err = os.MkdirAll(hashedDirectory, 0700)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var tempFile *os.File
|
|
tempFile, err = ioutil.TempFile(hashedDirectory, blobRef.FileBaseName()+".tmp")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
success := false // set true later
|
|
defer func() {
|
|
if !success {
|
|
fmt.Println("Removing temp file: ", tempFile.Name())
|
|
os.Remove(tempFile.Name())
|
|
}
|
|
}()
|
|
|
|
hash := blobRef.Hash()
|
|
var written int64
|
|
written, err = io.Copy(util.NewTee(hash, tempFile), source)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if err = tempFile.Close(); err != nil {
|
|
return
|
|
}
|
|
|
|
fileName := blobRef.FileName()
|
|
if err = os.Rename(tempFile.Name(), fileName); err != nil {
|
|
return
|
|
}
|
|
|
|
stat, err := os.Lstat(fileName)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !stat.IsRegular() || stat.Size != written {
|
|
return false, os.NewError("Written size didn't match.")
|
|
}
|
|
|
|
success = true
|
|
return true, nil
|
|
}
|
|
|
|
func handlePut(conn *http.Conn, req *http.Request) {
|
|
blobRef := ParsePath(req.URL.Path)
|
|
if blobRef == nil {
|
|
badRequestError(conn, "Malformed PUT URL.")
|
|
return
|
|
}
|
|
|
|
if !blobRef.IsSupported() {
|
|
badRequestError(conn, "unsupported object hash function")
|
|
return
|
|
}
|
|
|
|
_, err := receiveBlob(blobRef, req.Body)
|
|
if err != nil {
|
|
serverError(conn, err)
|
|
return
|
|
}
|
|
|
|
fmt.Fprint(conn, "OK")
|
|
}
|
|
|