func (u *Upload) monolithicUpload(w http.ResponseWriter, req *http.Request) { length := req.Header.Get(UPLOAD_HEADER_CONTENT_LENGTH) if length == "" { panic(fmt.Errorf("'%s' must be set in the header for a monolithic upload", UPLOAD_HEADER_CONTENT_LENGTH)) } nlen, err := strconv.ParseInt(length, 10, 64) location := req.Header.Get(UPLOAD_HEADER_LOCATION) if location == "" { panic(fmt.Errorf("'%s' must be set in the header for a monolithic upload", UPLOAD_HEADER_LOCATION)) } vars := mux.Vars(req) token, _ := vars["token"] digest := req.URL.Query().Get("digest") tmpFile := u.makeTempFilePath(location, token) if !lib.IsFile(tmpFile) { w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "cannot find the temporary file at %s, have you started a upload yet?", tmpFile) return } f, err := os.OpenFile(tmpFile, os.O_WRONLY, 0666) if err != nil { panic(fmt.Errorf("cannot open the file[%s], %v", tmpFile, err)) } deleteFile := func() { os.Remove(tmpFile) } n, err := io.Copy(f, req.Body) if err != nil { defer deleteFile() panic(fmt.Errorf("failed to write to %s, %v", tmpFile, err)) } if n != nlen { defer deleteFile() panic(fmt.Errorf("the file size[%d] is not matching '%s'[%d]", n, UPLOAD_HEADER_CONTENT_LENGTH, nlen)) } if err := os.Rename(tmpFile, location); err != nil { defer deleteFile() panic(fmt.Errorf("failed rename the file[%s] to %s, %v", tmpFile, location, err)) } sum := lib.Md5(location) if sum != digest { defer deleteFile() panic(fmt.Errorf("corrupted file; expected MD5[%s] but got %s", digest, sum)) } w.WriteHeader(http.StatusCreated) }
func (u *Upload) start(w http.ResponseWriter, req *http.Request) { location := req.Header.Get(UPLOAD_HEADER_LOCATION) if location == "" { panic(fmt.Errorf("'%s' must be set in the header for starting a upload", UPLOAD_HEADER_LOCATION)) } else if !path.IsAbs(location) { panic(fmt.Errorf("%s[%s] must be an absolute path", UPLOAD_HEADER_LOCATION, location)) } digest := req.Header.Get(UPLOAD_HEADER_DIGEST) if digest == "" { panic(fmt.Errorf("'%s' must be set in the header for starting a upload", UPLOAD_HEADER_DIGEST)) } if lib.IsFile(location) { if sum := lib.Md5(location); sum == digest { // for existing and same file, don't upload it w.WriteHeader(http.StatusNotModified) return } } if err := os.MkdirAll(path.Dir(location), os.ModeDir); err != nil { panic(fmt.Errorf("cannot create directory for the file[%s], %v", location, err)) } token := lib.RandomString() tmpFile := u.makeTempFilePath(location, token) f, err := os.Create(tmpFile) if err != nil { panic(fmt.Errorf("cannot create the file[%s], %v", tmpFile, err)) } f.Close() w.Header().Add(UPLOAD_HEADER_URL, Url(fmt.Sprintf("/upload/%s", token)).String()) w.Header().Add(UPLOAD_HEADER_TOKEN, token) w.WriteHeader(http.StatusAccepted) }