Example #1
0
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)
}
Example #2
0
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)
}