Index: Refactor mime type detection #391

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2020-07-21 14:43:45 +02:00
parent c704642f2e
commit 7d00e68d92
18 changed files with 169 additions and 99 deletions

View file

@ -1,4 +1,4 @@
FROM photoprism/development:20200715
FROM photoprism/development:20200721
# Set up project directory
WORKDIR "/go/src/github.com/photoprism/photoprism"

BIN
assets/examples/earth.avi Normal file

Binary file not shown.

BIN
assets/examples/earth.mov Normal file

Binary file not shown.

View file

@ -1,4 +1,4 @@
FROM photoprism/development:20200715 as build
FROM photoprism/development:20200721 as build
# Set up project directory
WORKDIR "/go/src/github.com/photoprism/photoprism"

View file

@ -41,6 +41,7 @@ RUN apt-get update && apt-get upgrade && \
make \
wget \
git \
gettext \
tzdata \
gconf-service

2
go.mod
View file

@ -18,13 +18,13 @@ require (
github.com/dsoprea/go-utility v0.0.0-20200717064901-2fccff4aa15e // indirect
github.com/dustin/go-humanize v1.0.0
github.com/gin-gonic/gin v1.6.3
github.com/go-errors/errors v1.1.1 // indirect
github.com/go-playground/validator/v10 v10.3.0 // indirect
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d
github.com/golang/protobuf v1.4.2 // indirect
github.com/google/open-location-code/go v0.0.0-20200603075809-e28188e71340
github.com/gorilla/websocket v1.4.2
github.com/gosimple/slug v1.9.0
github.com/h2non/filetype v1.1.0
github.com/jinzhu/gorm v1.9.14
github.com/jinzhu/inflection v1.0.0
github.com/json-iterator/go v1.1.10 // indirect

14
go.sum
View file

@ -46,29 +46,17 @@ github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4 h1:bVaiYo8amn7L
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
github.com/dsoprea/go-exif/v2 v2.0.0-20200520183328-015129a9efd5/go.mod h1:9EXlPeHfblFFnwu5UOqmP2eoZfJyAZ2Ri/Vki33ajO0=
github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4/go.mod h1:9EXlPeHfblFFnwu5UOqmP2eoZfJyAZ2Ri/Vki33ajO0=
github.com/dsoprea/go-exif/v2 v2.0.0-20200717063959-46b1a0cd1772 h1:M49UNOTa5sLju107lAoMsm93B/fHD02vWIoskmXMBm8=
github.com/dsoprea/go-exif/v2 v2.0.0-20200717063959-46b1a0cd1772/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc=
github.com/dsoprea/go-exif/v2 v2.0.0-20200717071058-9393e7afd446 h1:ruDG+2wFz+k/mDNy8x1UqWEItWNLXpvGlLv05+TlZt4=
github.com/dsoprea/go-exif/v2 v2.0.0-20200717071058-9393e7afd446/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc=
github.com/dsoprea/go-exif/v2 v2.0.0-20200721051611-3a80916d1fb8 h1:CDv1mPzK6J1vdCeXGoVdFKJqKKTTfnbsPIu9VcWkurM=
github.com/dsoprea/go-exif/v2 v2.0.0-20200721051611-3a80916d1fb8/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717063959-46b1a0cd1772 h1:l/wfrK3wEH7sYpJe+Y8ZdFJW3AmsDgPoAQq2RLgKPSQ=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717063959-46b1a0cd1772/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717071058-9393e7afd446 h1:96yylb+JH415u6V7ykNtnEBLaZUwS1S31TnAezcvnNE=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717071058-9393e7afd446/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20200721051611-3a80916d1fb8 h1:xMu5i9w1hAuS+0v7pw44wd4Y7eJoxfYiCkRQnEEvGd4=
github.com/dsoprea/go-exif/v3 v3.0.0-20200721051611-3a80916d1fb8/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20200520190950-3ae4ff88a0d1 h1:8Tbo+OYgg7i2G3fltmpWq1if1e752aMX7Zv/sNWWJUk=
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20200520190950-3ae4ff88a0d1/go.mod h1:UwRKreeVikXn5OarSnt4OqovcEjsIgZVuc5svj7G5w4=
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20200717090456-b3d9dcddffd1 h1:R/EEzpxqQxeEcJ/z0EFTI1U6XsuOnepyp5o1uZg5c2E=
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20200717090456-b3d9dcddffd1/go.mod h1:UwRKreeVikXn5OarSnt4OqovcEjsIgZVuc5svj7G5w4=
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb h1:gwjJjUr6FY7zAWVEueFPrcRHhd9+IK81TcItbqw2du4=
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM=
github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 h1:YDRiMEm32T60Kpm35YzOK9ZHgjsS1Qrid+XskNcsdp8=
github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM=
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200615034914-d40a386309d2 h1:8HmMqu64P4ZDGtcVwZDfmS4xuLXYjf2iery8teY7d9c=
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200615034914-d40a386309d2/go.mod h1:ZoOP3yUG0HD1T4IUjIFsz/2OAB2yB4YX6NSm4K+uJRg=
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200717085400-dd2ba56ee6b8 h1:cXCR9FOOkTEZ3t+asmy3lLv2AKYAah2igfx7WnNnVMc=
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20200717085400-dd2ba56ee6b8/go.mod h1:ZoOP3yUG0HD1T4IUjIFsz/2OAB2yB4YX6NSm4K+uJRg=
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 h1:VGFnZAcLwPpt1sHlAxml+pGLZz9A2s+K/s1YNhPC91Y=
@ -175,6 +163,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs=
github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg=
github.com/h2non/filetype v1.1.0 h1:Or/gjocJrJRNK/Cri/TDEKFjAR+cfG6eK65NGYB6gBA=
github.com/h2non/filetype v1.1.0/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=

View file

@ -61,8 +61,6 @@ func NewTestParams() *Params {
DetectNSFW: true,
UploadNSFW: false,
SidecarPath: fs.HiddenPath,
DarktableBin: "/usr/bin/darktable-cli",
ExifToolBin: "/usr/bin/exiftool",
AssetsPath: assetsPath,
StoragePath: testDataPath,
CachePath: testDataPath + "/cache",

View file

@ -11,6 +11,10 @@ func TestMain(m *testing.M) {
log = logrus.StandardLogger()
log.SetLevel(logrus.DebugLevel)
if err := os.Remove(".test.db"); err == nil {
log.Debugln("removed .test.db")
}
db := InitTestDb(os.Getenv("PHOTOPRISM_TEST_DRIVER"), os.Getenv("PHOTOPRISM_TEST_DSN"))
defer db.Close()

View file

@ -1,19 +1,21 @@
package photoprism
import (
"github.com/photoprism/photoprism/internal/config"
"github.com/stretchr/testify/assert"
"testing"
)
func TestFileName(t *testing.T) {
conf := config.TestConfig()
t.Run("sidecar", func(t *testing.T) {
assert.Equal(t, ".photoprism/test.jpg", FileName("sidecar", "test.jpg"))
})
t.Run("import", func(t *testing.T) {
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/storage/testdata/import/test.jpg", FileName("import", "test.jpg"))
assert.Equal(t, conf.ImportPath()+"/test.jpg", FileName("import", "test.jpg"))
})
t.Run("examples", func(t *testing.T) {
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/examples/test.jpg", FileName("examples", "test.jpg"))
assert.Equal(t, conf.ExamplesPath()+"/test.jpg", FileName("examples", "test.jpg"))
})
}

View file

@ -294,32 +294,44 @@ func (m *MediaFile) RelatedFiles(stripSequence bool) (result RelatedFiles, err e
matches = append(matches, name)
}
for _, filename := range matches {
resultFile, err := NewMediaFile(filename)
for _, fileName := range matches {
f, err := NewMediaFile(fileName)
if err != nil {
log.Warnf("mediafile: %s in %s", err, txt.Quote(filepath.Base(fileName)))
continue
}
if result.Main == nil && resultFile.IsJpeg() {
result.Main = resultFile
} else if resultFile.IsRaw() {
result.Main = resultFile
} else if resultFile.IsHEIF() {
result.Main = resultFile
} else if resultFile.IsJpeg() && len(result.Main.FileName()) > len(resultFile.FileName()) {
result.Main = resultFile
} else if resultFile.IsImageOther() {
result.Main = resultFile
} else if resultFile.IsVideo() {
result.Main = resultFile
if f.FileSize() == 0 {
log.Warnf("mediafile: %s is empty", txt.Quote(filepath.Base(fileName)))
continue
}
result.Files = append(result.Files, resultFile)
if result.Main == nil && f.IsJpeg() {
result.Main = f
} else if f.IsRaw() {
result.Main = f
} else if f.IsHEIF() {
result.Main = f
} else if f.IsJpeg() && len(result.Main.FileName()) > len(f.FileName()) {
result.Main = f
} else if f.IsImageOther() {
result.Main = f
} else if f.IsVideo() {
result.Main = f
}
result.Files = append(result.Files, f)
}
if result.Main == nil {
return result, fmt.Errorf("no main file found for %s", txt.Quote(m.BaseName()))
if len(result.Files) == 0 || result.Main == nil {
t := m.MimeType()
if t == "" {
t = "unknown type"
}
return result, fmt.Errorf("no supported files found for %s (%s)", txt.Quote(m.BaseName()), t)
}
// Add hidden JPEG if exists.
@ -622,11 +634,26 @@ func (m *MediaFile) IsGif() bool {
return m.MimeType() == fs.MimeTypeGif
}
// IsTiff returns true if this is a TIFF file.
func (m *MediaFile) IsTiff() bool {
return m.HasFileType(fs.TypeTiff) && m.MimeType() == fs.MimeTypeTiff
}
// IsHEIF returns true if this is a High Efficiency Image File Format file.
func (m *MediaFile) IsHEIF() bool {
return m.MimeType() == fs.MimeTypeHEIF
}
// IsBitmap returns true if this is a bitmap file.
func (m *MediaFile) IsBitmap() bool {
return m.MimeType() == fs.MimeTypeBitmap
}
// IsVideo returns true if this is a video file.
func (m *MediaFile) IsVideo() bool {
return strings.HasPrefix(m.MimeType(), "video/")
}
// IsJson return true if this media file is a json sidecar file.
func (m *MediaFile) IsJson() bool {
return m.HasFileType(fs.TypeJson)
@ -641,6 +668,8 @@ func (m *MediaFile) FileType() fs.FileType {
return fs.TypePng
case m.IsGif():
return fs.TypeGif
case m.IsHEIF():
return fs.TypeHEIF
case m.IsBitmap():
return fs.TypeBitmap
default:
@ -667,11 +696,6 @@ func (m *MediaFile) IsRaw() bool {
return m.HasFileType(fs.TypeRaw)
}
// IsTiff returns true if this is a TIFF file.
func (m *MediaFile) IsTiff() bool {
return m.HasFileType(fs.TypeTiff)
}
// IsImageOther returns true if this is a PNG, GIF, BMP or TIFF file.
func (m *MediaFile) IsImageOther() bool {
switch {
@ -682,11 +706,6 @@ func (m *MediaFile) IsImageOther() bool {
}
}
// IsHEIF returns true if this is a High Efficiency Image File Format file.
func (m *MediaFile) IsHEIF() bool {
return m.HasFileType(fs.TypeHEIF)
}
// IsXMP returns true if this is a XMP sidecar file.
func (m *MediaFile) IsXMP() bool {
return m.FileType() == fs.TypeXMP
@ -697,14 +716,9 @@ func (m *MediaFile) IsSidecar() bool {
return m.MediaType() == fs.MediaSidecar
}
// IsVideo returns true if this is a video file.
func (m *MediaFile) IsVideo() bool {
return m.MediaType() == fs.MediaVideo
}
// IsPlayableVideo returns true if this is a supported video file format.
func (m *MediaFile) IsPlayableVideo() bool {
return m.MediaType() == fs.MediaVideo && m.HasFileType(fs.TypeMP4)
return m.IsVideo() && m.HasFileType(fs.TypeMP4)
}
// IsPhoto returns true if this file is a photo / image.

View file

@ -3,6 +3,7 @@ package photoprism
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/photoprism/photoprism/internal/config"
@ -522,6 +523,8 @@ func TestMediaFile_RelatedFiles(t *testing.T) {
t.Fatalf("length is %d, should be 4", len(related.Files))
}
t.Logf("FILE: %s, %s", related.Main.FileType(), related.Main.MimeType())
assert.Equal(t, "2015-02-04.jpg", related.Main.BaseName())
assert.Equal(t, "2015-02-04.jpg", related.Files[0].BaseName())
@ -650,12 +653,12 @@ func TestMediaFile_RelName(t *testing.T) {
}
t.Run("directory with end slash", func(t *testing.T) {
filename := mediaFile.RelName("/go/src/github.com/photoprism/photoprism/assets/")
filename := mediaFile.RelName(conf.AssetsPath())
assert.Equal(t, "examples/tree_white.jpg", filename)
})
t.Run("directory without end slash", func(t *testing.T) {
filename := mediaFile.RelName("/go/src/github.com/photoprism/photoprism/assets")
filename := mediaFile.RelName(conf.AssetsPath())
assert.Equal(t, "examples/tree_white.jpg", filename)
})
t.Run("directory not part of filename", func(t *testing.T) {
@ -663,7 +666,7 @@ func TestMediaFile_RelName(t *testing.T) {
assert.Equal(t, conf.ExamplesPath()+"/tree_white.jpg", filename)
})
t.Run("directory equals example path", func(t *testing.T) {
filename := mediaFile.RelName("/go/src/github.com/photoprism/photoprism/assets/examples")
filename := mediaFile.RelName(conf.ExamplesPath())
assert.Equal(t, "tree_white.jpg", filename)
})
}
@ -679,11 +682,11 @@ func TestMediaFile_RelativePath(t *testing.T) {
}
t.Run("directory with end slash", func(t *testing.T) {
path := mediaFile.RelPath("/go/src/github.com/photoprism/photoprism/assets/")
path := mediaFile.RelPath(conf.AssetsPath() + "/")
assert.Equal(t, "examples", path)
})
t.Run("directory without end slash", func(t *testing.T) {
path := mediaFile.RelPath("/go/src/github.com/photoprism/photoprism/assets")
path := mediaFile.RelPath(conf.AssetsPath())
assert.Equal(t, "examples", path)
})
t.Run("directory equals filepath", func(t *testing.T) {
@ -692,7 +695,7 @@ func TestMediaFile_RelativePath(t *testing.T) {
})
t.Run("directory does not match filepath", func(t *testing.T) {
path := mediaFile.RelPath("xxx")
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/examples", path)
assert.Equal(t, conf.ExamplesPath(), path)
})
mediaFile, err = NewMediaFile(conf.ExamplesPath() + "/.photoprism/example.jpg")
@ -724,15 +727,15 @@ func TestMediaFile_RelativeBasename(t *testing.T) {
}
t.Run("directory with end slash", func(t *testing.T) {
basename := mediaFile.RelPrefix("/go/src/github.com/photoprism/photoprism/assets/", true)
basename := mediaFile.RelPrefix(conf.AssetsPath()+"/", true)
assert.Equal(t, "examples/tree_white", basename)
})
t.Run("directory without end slash", func(t *testing.T) {
basename := mediaFile.RelPrefix("/go/src/github.com/photoprism/photoprism/assets", true)
basename := mediaFile.RelPrefix(conf.AssetsPath(), true)
assert.Equal(t, "examples/tree_white", basename)
})
t.Run("directory equals example path", func(t *testing.T) {
basename := mediaFile.RelPrefix("/go/src/github.com/photoprism/photoprism/assets/examples/", true)
basename := mediaFile.RelPrefix(conf.ExamplesPath(), true)
assert.Equal(t, "tree_white", basename)
})
@ -796,7 +799,7 @@ func TestMediaFile_MimeType(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "application/octet-stream", mediaFile.MimeType())
assert.Equal(t, "image/tiff", mediaFile.MimeType())
})
@ -805,7 +808,7 @@ func TestMediaFile_MimeType(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "text/plain; charset=utf-8", mediaFile.MimeType())
assert.Equal(t, "", mediaFile.MimeType())
})
t.Run("iphone_7.json", func(t *testing.T) {
@ -813,7 +816,7 @@ func TestMediaFile_MimeType(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "text/plain; charset=utf-8", mediaFile.MimeType())
assert.Equal(t, "", mediaFile.MimeType())
})
t.Run("iphone_7.heic", func(t *testing.T) {
@ -821,7 +824,7 @@ func TestMediaFile_MimeType(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "application/octet-stream", mediaFile.MimeType())
assert.Equal(t, "image/heif", mediaFile.MimeType())
})
t.Run("IMG_4120.AAE", func(t *testing.T) {
@ -829,7 +832,31 @@ func TestMediaFile_MimeType(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "text/xml; charset=utf-8", mediaFile.MimeType())
assert.Equal(t, "", mediaFile.MimeType())
})
t.Run("earth.mov", func(t *testing.T) {
if f, err := NewMediaFile(filepath.Join(conf.ExamplesPath(), "earth.mov")); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, "video/quicktime", f.MimeType())
}
})
t.Run("blue-go-video.mp4", func(t *testing.T) {
if f, err := NewMediaFile(filepath.Join(conf.ExamplesPath(), "blue-go-video.mp4")); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, "video/mp4", f.MimeType())
}
})
t.Run("earth.avi", func(t *testing.T) {
if f, err := NewMediaFile(filepath.Join(conf.ExamplesPath(), "earth.avi")); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, "video/x-msvideo", f.MimeType())
}
})
}
@ -1087,6 +1114,7 @@ func TestMediaFile_IsRaw(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, true, mediaFile.IsRaw())
})
t.Run("/elephants.jpg", func(t *testing.T) {
@ -1134,7 +1162,7 @@ func TestMediaFile_IsTiff(t *testing.T) {
t.Fatal(err)
}
assert.Equal(t, fs.TypeJson, mediaFile.FileType())
assert.Equal(t, "text/plain; charset=utf-8", mediaFile.MimeType())
assert.Equal(t, "", mediaFile.MimeType())
assert.Equal(t, false, mediaFile.IsTiff())
})
t.Run("/purple.tiff", func(t *testing.T) {
@ -1145,7 +1173,7 @@ func TestMediaFile_IsTiff(t *testing.T) {
t.Fatal(err)
}
assert.Equal(t, fs.TypeTiff, mediaFile.FileType())
assert.Equal(t, "application/octet-stream", mediaFile.MimeType())
assert.Equal(t, "image/tiff", mediaFile.MimeType())
assert.Equal(t, true, mediaFile.IsTiff())
})
t.Run("/example.tiff", func(t *testing.T) {
@ -1156,7 +1184,7 @@ func TestMediaFile_IsTiff(t *testing.T) {
t.Fatal(err)
}
assert.Equal(t, fs.TypeTiff, mediaFile.FileType())
assert.Equal(t, "application/octet-stream", mediaFile.MimeType())
assert.Equal(t, "image/tiff", mediaFile.MimeType())
assert.Equal(t, true, mediaFile.IsTiff())
})
}
@ -1285,7 +1313,7 @@ func TestMediaFile_IsSidecar(t *testing.T) {
}
func TestMediaFile_IsPhoto(t *testing.T) {
t.Run("/iphone_7.json", func(t *testing.T) {
t.Run("iphone_7.json", func(t *testing.T) {
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/iphone_7.json")
@ -1294,14 +1322,14 @@ func TestMediaFile_IsPhoto(t *testing.T) {
}
assert.Equal(t, false, mediaFile.IsPhoto())
})
t.Run("/iphone_7.xmp", func(t *testing.T) {
t.Run("iphone_7.xmp", func(t *testing.T) {
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/iphone_7.xmp")
assert.Nil(t, err)
assert.Equal(t, false, mediaFile.IsPhoto())
})
t.Run("/iphone_7.heic", func(t *testing.T) {
t.Run("iphone_7.heic", func(t *testing.T) {
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/iphone_7.heic")
@ -1310,7 +1338,7 @@ func TestMediaFile_IsPhoto(t *testing.T) {
}
assert.Equal(t, true, mediaFile.IsPhoto())
})
t.Run("/canon_eos_6d.dng", func(t *testing.T) {
t.Run("canon_eos_6d.dng", func(t *testing.T) {
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/canon_eos_6d.dng")
@ -1319,7 +1347,7 @@ func TestMediaFile_IsPhoto(t *testing.T) {
}
assert.Equal(t, true, mediaFile.IsPhoto())
})
t.Run("/elephants.jpg", func(t *testing.T) {
t.Run("elephants.jpg", func(t *testing.T) {
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/elephants.jpg")
@ -1329,25 +1357,37 @@ func TestMediaFile_IsPhoto(t *testing.T) {
}
func TestMediaFile_IsVideo(t *testing.T) {
t.Run("/christmas.mp4", func(t *testing.T) {
conf := config.TestConfig()
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/christmas.mp4")
if err != nil {
t.Run("christmas.mp4", func(t *testing.T) {
if f, err := NewMediaFile(filepath.Join(conf.ExamplesPath(), "christmas.mp4")); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, false, f.IsPhoto())
assert.Equal(t, true, f.IsVideo())
assert.Equal(t, false, f.IsJson())
assert.Equal(t, false, f.IsSidecar())
}
assert.Equal(t, false, mediaFile.IsPhoto())
})
t.Run("/canon_eos_6d.dng", func(t *testing.T) {
conf := config.TestConfig()
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/canon_eos_6d.dng")
if err != nil {
t.Run("canon_eos_6d.dng", func(t *testing.T) {
if f, err := NewMediaFile(filepath.Join(conf.ExamplesPath(), "canon_eos_6d.dng")); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, true, f.IsPhoto())
assert.Equal(t, false, f.IsVideo())
assert.Equal(t, false, f.IsJson())
assert.Equal(t, false, f.IsSidecar())
}
})
t.Run("iphone_7.json", func(t *testing.T) {
if f, err := NewMediaFile(filepath.Join(conf.ExamplesPath(), "iphone_7.json")); err != nil {
t.Fatal(err)
} else {
assert.Equal(t, false, f.IsPhoto())
assert.Equal(t, false, f.IsVideo())
assert.Equal(t, true, f.IsJson())
assert.Equal(t, true, f.IsSidecar())
}
assert.Equal(t, true, mediaFile.IsPhoto())
})
}
@ -1844,7 +1884,7 @@ func TestMediaFile_JsonName(t *testing.T) {
}
name := mediaFile.JsonName()
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/examples/blue-go-video.mp4.json", name)
assert.True(t, strings.HasSuffix(name, "/assets/examples/blue-go-video.mp4.json"))
})
}
@ -1941,7 +1981,7 @@ func TestMediaFile_SubDirectory(t *testing.T) {
}
subdir := mediaFile.SubDir("xxx")
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/examples/xxx", subdir)
assert.True(t, strings.HasSuffix(subdir, "/assets/examples/xxx"))
})
}

View file

@ -12,6 +12,10 @@ func TestMain(m *testing.M) {
log = logrus.StandardLogger()
log.SetLevel(logrus.DebugLevel)
if err := os.Remove(".test.db"); err == nil {
log.Debugln("removed .test.db")
}
c := config.TestConfig()
SetConfig(c)

View file

@ -2,6 +2,7 @@ package photoprism
import (
"os"
"strings"
"testing"
"github.com/disintegration/imaging"
@ -60,11 +61,16 @@ func TestThumb_Filename(t *testing.T) {
t.Run("", func(t *testing.T) {
filename, err := thumb.Filename("99988", thumbsPath, 150, 150, thumb.ResampleFit, thumb.ResampleNearestNeighbor)
assert.Nil(t, err)
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/storage/testdata/cache/_tmp/9/9/9/99988_150x150_fit.jpg", filename)
if err != nil {
t.Fatal(err)
}
assert.True(t, strings.HasSuffix(filename, "/storage/testdata/cache/_tmp/9/9/9/99988_150x150_fit.jpg"))
})
t.Run("hash too short", func(t *testing.T) {
_, err := thumb.Filename("999", thumbsPath, 150, 150, thumb.ResampleFit, thumb.ResampleNearestNeighbor)
if err == nil {
t.FailNow()
}

View file

View file

@ -13,6 +13,10 @@ func TestMain(m *testing.M) {
log = logrus.StandardLogger()
log.SetLevel(logrus.DebugLevel)
if err := os.Remove(".test.db"); err == nil {
log.Debugln("removed .test.db")
}
db := entity.InitTestDb(os.Getenv("PHOTOPRISM_TEST_DRIVER"), os.Getenv("PHOTOPRISM_TEST_DSN"))
defer db.Close()

View file

@ -12,6 +12,10 @@ func TestMain(m *testing.M) {
log = logrus.StandardLogger()
log.SetLevel(logrus.DebugLevel)
if err := os.Remove(".test.db"); err == nil {
log.Debugln("removed .test.db")
}
c := config.TestConfig()
code := m.Run()

View file

@ -1,8 +1,9 @@
package fs
import (
"net/http"
"os"
"github.com/h2non/filetype"
)
const (
@ -10,6 +11,8 @@ const (
MimeTypePng = "image/png"
MimeTypeGif = "image/gif"
MimeTypeBitmap = "image/bmp"
MimeTypeTiff = "image/tiff"
MimeTypeHEIF = "image/heif"
)
// MimeType returns the mime type of a file, empty string if unknown.
@ -22,14 +25,14 @@ func MimeType(filename string) string {
defer handle.Close()
// Only the first 512 bytes are used to sniff the content type.
buffer := make([]byte, 512)
// Only the first 261 bytes are used to sniff the content type.
buffer := make([]byte, 261)
_, err = handle.Read(buffer)
if err != nil {
if _, err := handle.Read(buffer); err != nil {
return ""
} else if t, err := filetype.Get(buffer); err != nil {
return ""
} else {
return t.MIME.Value
}
return http.DetectContentType(buffer)
}