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") }