diff --git a/api/get_cover_art.go b/api/get_cover_art.go
index 98236d4aa..c2f1942d6 100644
--- a/api/get_cover_art.go
+++ b/api/get_cover_art.go
@@ -3,64 +3,32 @@ package api
 import (
 	"github.com/astaxie/beego"
 	"github.com/deluan/gosonic/api/responses"
-	"github.com/deluan/gosonic/domain"
+	"github.com/deluan/gosonic/engine"
 	"github.com/deluan/gosonic/utils"
-	"github.com/dhowden/tag"
 	"github.com/karlkfi/inject"
-	"io/ioutil"
-	"os"
 )
 
 type GetCoverArtController struct {
 	BaseAPIController
-	repo domain.MediaFileRepository
+	cover engine.Cover
 }
 
 func (c *GetCoverArtController) Prepare() {
-	inject.ExtractAssignable(utils.Graph, &c.repo)
+	inject.ExtractAssignable(utils.Graph, &c.cover)
 }
 
 // TODO accept size parameter
 func (c *GetCoverArtController) Get() {
 	id := c.RequiredParamString("id", "id parameter required")
 
-	mf, err := c.repo.Get(id)
-	if err != nil {
-		beego.Error("Error reading mediafile", id, "from the database", ":", err)
-		c.SendError(responses.ERROR_GENERIC, "Internal error")
+	err := c.cover.GetCover(id, 0, c.Ctx.ResponseWriter)
+
+	switch {
+	case err == engine.DataNotFound:
+		beego.Error(err, "Id:", id)
+		c.SendError(responses.ERROR_DATA_NOT_FOUND, "Directory not found")
+	case err != nil:
+		beego.Error(err)
+		c.SendError(responses.ERROR_GENERIC, "Internal Error")
 	}
-
-	var img []byte
-
-	if mf != nil && mf.HasCoverArt {
-		img, err = readFromTag(mf.Path)
-		beego.Debug("Serving cover art from", mf.Path)
-	} else {
-		img, err = ioutil.ReadFile("static/default_cover.jpg")
-		beego.Debug("Serving default cover art")
-	}
-
-	if err != nil {
-		beego.Error("Could not retrieve cover art", id, ":", err)
-		c.SendError(responses.ERROR_DATA_NOT_FOUND, "cover art not available")
-	}
-
-	c.Ctx.Output.Body(img)
-}
-
-func readFromTag(path string) ([]byte, error) {
-	f, err := os.Open(path)
-	if err != nil {
-		beego.Warn("Error opening file", path, "-", err)
-		return nil, err
-	}
-	defer f.Close()
-
-	m, err := tag.ReadFrom(f)
-	if err != nil {
-		beego.Warn("Error reading tag from file", path, "-", err)
-		return nil, err
-	}
-
-	return m.Picture().Data, nil
 }
diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go
index 28d28c916..131e46fca 100644
--- a/conf/inject_definitions.go
+++ b/conf/inject_definitions.go
@@ -19,4 +19,5 @@ func init() {
 	utils.DefineSingleton(new(engine.PropertyRepository), persistence.NewPropertyRepository)
 	utils.DefineSingleton(new(engine.Browser), engine.NewBrowser)
 	utils.DefineSingleton(new(engine.ListGenerator), engine.NewListGenerator)
+	utils.DefineSingleton(new(engine.Cover), engine.NewCover)
 }
diff --git a/engine/cover.go b/engine/cover.go
new file mode 100644
index 000000000..8f2feb193
--- /dev/null
+++ b/engine/cover.go
@@ -0,0 +1,59 @@
+package engine
+
+import (
+	"io"
+	"io/ioutil"
+	"os"
+
+	"github.com/deluan/gosonic/domain"
+	"github.com/dhowden/tag"
+)
+
+type Cover interface {
+	GetCover(id string, size int, out io.Writer) error
+}
+
+type cover struct {
+	mfileRepo domain.MediaFileRepository
+}
+
+func NewCover(mr domain.MediaFileRepository) Cover {
+	return cover{mr}
+}
+
+func (c cover) GetCover(id string, size int, out io.Writer) error {
+	mf, err := c.mfileRepo.Get(id)
+	if err != nil {
+		return err
+	}
+
+	var img []byte
+
+	if mf != nil && mf.HasCoverArt {
+		img, err = readFromTag(mf.Path)
+	} else {
+		img, err = ioutil.ReadFile("static/default_cover.jpg")
+	}
+
+	if err != nil {
+		return DataNotFound
+	}
+
+	_, err = out.Write(img)
+	return err
+}
+
+func readFromTag(path string) ([]byte, error) {
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	m, err := tag.ReadFrom(f)
+	if err != nil {
+		return nil, err
+	}
+
+	return m.Picture().Data, nil
+}