diff --git a/modules/upload/filetype.go b/modules/upload/filetype.go
new file mode 100644
index 0000000000..1ec7324ed3
--- /dev/null
+++ b/modules/upload/filetype.go
@@ -0,0 +1,49 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package upload
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"code.gitea.io/gitea/modules/log"
+)
+
+// ErrFileTypeForbidden not allowed file type error
+type ErrFileTypeForbidden struct {
+	Type string
+}
+
+// IsErrFileTypeForbidden checks if an error is a ErrFileTypeForbidden.
+func IsErrFileTypeForbidden(err error) bool {
+	_, ok := err.(ErrFileTypeForbidden)
+	return ok
+}
+
+func (err ErrFileTypeForbidden) Error() string {
+	return fmt.Sprintf("File type is not allowed: %s", err.Type)
+}
+
+// VerifyAllowedContentType validates a file is allowed to be uploaded.
+func VerifyAllowedContentType(buf []byte, allowedTypes []string) error {
+	fileType := http.DetectContentType(buf)
+
+	allowed := false
+	for _, t := range allowedTypes {
+		t := strings.Trim(t, " ")
+		if t == "*/*" || t == fileType {
+			allowed = true
+			break
+		}
+	}
+
+	if !allowed {
+		log.Info("Attachment with type %s blocked from upload", fileType)
+		return ErrFileTypeForbidden{Type: fileType}
+	}
+
+	return nil
+}
diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go
index f85787bc59..d0eb3d4ae1 100644
--- a/routers/api/v1/repo/release_attachment.go
+++ b/routers/api/v1/repo/release_attachment.go
@@ -5,13 +5,12 @@
 package repo
 
 import (
-	"errors"
-	"net/http"
 	"strings"
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/upload"
 
 	api "code.gitea.io/gitea/modules/structs"
 )
@@ -177,20 +176,9 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
 	}
 
 	// Check if the filetype is allowed by the settings
-	fileType := http.DetectContentType(buf)
-
-	allowedTypes := strings.Split(setting.AttachmentAllowedTypes, ",")
-	allowed := false
-	for _, t := range allowedTypes {
-		t := strings.Trim(t, " ")
-		if t == "*/*" || t == fileType {
-			allowed = true
-			break
-		}
-	}
-
-	if !allowed {
-		ctx.Error(400, "DetectContentType", errors.New("File type is not allowed"))
+	err = upload.VerifyAllowedContentType(buf, strings.Split(setting.AttachmentAllowedTypes, ","))
+	if err != nil {
+		ctx.Error(400, "DetectContentType", err)
 		return
 	}
 
diff --git a/routers/repo/attachment.go b/routers/repo/attachment.go
index 8913e63015..a07a2a8ace 100644
--- a/routers/repo/attachment.go
+++ b/routers/repo/attachment.go
@@ -6,13 +6,13 @@ package repo
 
 import (
 	"fmt"
-	"net/http"
 	"strings"
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/upload"
 )
 
 func renderAttachmentSettings(ctx *context.Context) {
@@ -42,21 +42,10 @@ func UploadAttachment(ctx *context.Context) {
 	if n > 0 {
 		buf = buf[:n]
 	}
-	fileType := http.DetectContentType(buf)
 
-	allowedTypes := strings.Split(setting.AttachmentAllowedTypes, ",")
-	allowed := false
-	for _, t := range allowedTypes {
-		t := strings.Trim(t, " ")
-		if t == "*/*" || t == fileType {
-			allowed = true
-			break
-		}
-	}
-
-	if !allowed {
-		log.Info("Attachment with type %s blocked from upload", fileType)
-		ctx.Error(400, ErrFileTypeForbidden.Error())
+	err = upload.VerifyAllowedContentType(buf, strings.Split(setting.AttachmentAllowedTypes, ","))
+	if err != nil {
+		ctx.Error(400, err.Error())
 		return
 	}
 
diff --git a/routers/repo/editor.go b/routers/repo/editor.go
index 062ecfebf7..f3327017e5 100644
--- a/routers/repo/editor.go
+++ b/routers/repo/editor.go
@@ -7,7 +7,6 @@ package repo
 import (
 	"fmt"
 	"io/ioutil"
-	"net/http"
 	"path"
 	"strings"
 
@@ -20,6 +19,7 @@ import (
 	"code.gitea.io/gitea/modules/repofiles"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
+	"code.gitea.io/gitea/modules/upload"
 	"code.gitea.io/gitea/modules/util"
 )
 
@@ -594,20 +594,11 @@ func UploadFileToServer(ctx *context.Context) {
 	if n > 0 {
 		buf = buf[:n]
 	}
-	fileType := http.DetectContentType(buf)
 
 	if len(setting.Repository.Upload.AllowedTypes) > 0 {
-		allowed := false
-		for _, t := range setting.Repository.Upload.AllowedTypes {
-			t := strings.Trim(t, " ")
-			if t == "*/*" || t == fileType {
-				allowed = true
-				break
-			}
-		}
-
-		if !allowed {
-			ctx.Error(400, ErrFileTypeForbidden.Error())
+		err = upload.VerifyAllowedContentType(buf, setting.Repository.Upload.AllowedTypes)
+		if err != nil {
+			ctx.Error(400, err.Error())
 			return
 		}
 	}
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index 3904d29532..72e0357e6c 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -41,8 +41,6 @@ const (
 )
 
 var (
-	// ErrFileTypeForbidden not allowed file type error
-	ErrFileTypeForbidden = errors.New("File type is not allowed")
 	// ErrTooManyFiles upload too many files
 	ErrTooManyFiles = errors.New("Maximum number of files to upload exceeded")
 	// IssueTemplateCandidates issue templates