diff --git a/handlers.go b/handlers.go
index 08ce727..0da8ad5 100644
--- a/handlers.go
+++ b/handlers.go
@@ -18,6 +18,12 @@ import (
 	bolt "go.etcd.io/bbolt"
 )
 
+const (
+	// formParseMaxMemory value is based on the default value that is used in
+	// Request.ParseMultipartForm.
+	formParseMaxMemory = 32 << 20 // 32 MB
+)
+
 type viewPaste uint
 
 const (
@@ -223,25 +229,37 @@ func (rl *rushlink) viewActionSuccess(w http.ResponseWriter, r *http.Request, p
 }
 
 func (rl *rushlink) newPasteHandler(w http.ResponseWriter, r *http.Request) {
-	file, fileHeader, err := r.FormFile("file")
-	if err == nil {
-		rl.newFileUploadPasteHandler(w, r, file, *fileHeader)
-		return
-	} else if err == http.ErrMissingFile {
-		// Fallthrough
-	} else {
+	if err := r.ParseMultipartForm(formParseMaxMemory); err != nil {
 		msg := fmt.Sprintf("could not parse form: %v\n", err)
 		rl.renderError(w, r, http.StatusBadRequest, msg)
 		return
 	}
 
-	shorten := r.FormValue("shorten")
-	if shorten != "" {
-		rl.newRedirectPasteHandler(w, r, shorten)
+	fileHeaders, fileHeadersPrs := r.MultipartForm.File["file"]
+	shortens, shortensPrs := r.MultipartForm.Value["shorten"]
+
+	if !shortensPrs && !fileHeadersPrs {
+		rl.renderError(w, r, http.StatusBadRequest, "no 'file' and no 'shorten' fields given in form\n")
+		return
+	}
+	if shortensPrs && fileHeadersPrs {
+		rl.renderError(w, r, http.StatusBadRequest, "both 'file' and 'shorten' fields provided in form\n")
+		return
+	}
+	if shortensPrs {
+		rl.newRedirectPasteHandler(w, r, shortens[0])
+		return
+	}
+	if fileHeadersPrs {
+		fileHeader := fileHeaders[0]
+		file, err := fileHeader.Open()
+		if err != nil {
+			rl.renderInternalServerError(w, r, err)
+			return
+		}
+		rl.newFileUploadPasteHandler(w, r, file, *fileHeader)
 		return
 	}
-
-	rl.renderError(w, r, http.StatusBadRequest, "no 'file' and no 'shorten' fields given in form\n")
 }
 
 func (rl *rushlink) newFileUploadPasteHandler(w http.ResponseWriter, r *http.Request, file multipart.File, header multipart.FileHeader) {