clean up and add comments
This commit is contained in:
@@ -38,11 +38,11 @@ type Config struct {
|
||||
Debug Debug
|
||||
HTTP HTTP
|
||||
Tracing Tracing
|
||||
FilesystemStorage FilesystemStorage
|
||||
FileSystemStorage FileSystemStorage
|
||||
}
|
||||
|
||||
// FilesystemStorage defines the available filesystem storage configuration.
|
||||
type FilesystemStorage struct {
|
||||
// FileSystemStorage defines the available filesystem storage configuration.
|
||||
type FileSystemStorage struct {
|
||||
RootDirectory string
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ func NewService(opts ...Option) Service {
|
||||
config: options.Config,
|
||||
mux: m,
|
||||
manager: thumbnails.SimpleManager{
|
||||
Storage: storage.NewInMemoryStorage(),
|
||||
Storage: storage.NewFileSystemStorage(options.Config.FileSystemStorage),
|
||||
},
|
||||
source: imgsource.WebDav{
|
||||
Basepath: "http://localhost:9140/remote.php/webdav/",
|
||||
@@ -71,7 +71,7 @@ func (g Thumbnails) Thumbnails(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("can't encode that"))
|
||||
return
|
||||
}
|
||||
ctx := thumbnails.ThumbnailContext{
|
||||
ctx := thumbnails.Context{
|
||||
Width: width,
|
||||
Height: height,
|
||||
ImagePath: filePath,
|
||||
|
||||
@@ -8,31 +8,42 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Encoder encodes the thumbnail to a specific format.
|
||||
type Encoder interface {
|
||||
// Encode encodes the image to a format.
|
||||
Encode(io.Writer, image.Image) error
|
||||
// Types returns the formats suffixes.
|
||||
Types() []string
|
||||
}
|
||||
|
||||
// PngEncoder encodes to png
|
||||
type PngEncoder struct{}
|
||||
|
||||
// Encode encodes to png format
|
||||
func (e PngEncoder) Encode(w io.Writer, i image.Image) error {
|
||||
return png.Encode(w, i)
|
||||
}
|
||||
|
||||
// Types returns the png suffix
|
||||
func (e PngEncoder) Types() []string {
|
||||
return []string{"png"}
|
||||
}
|
||||
|
||||
// JpegEncoder encodes to jpg.
|
||||
type JpegEncoder struct{}
|
||||
|
||||
// Encode encodes to jpg
|
||||
func (e JpegEncoder) Encode(w io.Writer, i image.Image) error {
|
||||
return jpeg.Encode(w, i, nil)
|
||||
}
|
||||
|
||||
// Types returns the jpg suffixes.
|
||||
func (e JpegEncoder) Types() []string {
|
||||
return []string{"jpeg", "jpg"}
|
||||
}
|
||||
|
||||
// EncoderForType returns the encoder for a given file type
|
||||
// or nil if the type is not supported.
|
||||
func EncoderForType(fileType string) Encoder {
|
||||
switch strings.ToLower(fileType) {
|
||||
case "png":
|
||||
|
||||
@@ -11,12 +11,21 @@ import (
|
||||
"github.com/owncloud/ocis-thumbnails/pkg/config"
|
||||
)
|
||||
|
||||
type FileSystem struct {
|
||||
cfg config.FilesystemStorage
|
||||
// NewFileSystemStorage creates a new instanz of FileSystem
|
||||
func NewFileSystemStorage(cfg config.FileSystemStorage) FileSystem {
|
||||
return FileSystem{
|
||||
dir: cfg.RootDirectory,
|
||||
}
|
||||
}
|
||||
|
||||
// FileSystem represents a storage for the thumbnails using the local file system.
|
||||
type FileSystem struct {
|
||||
dir string
|
||||
}
|
||||
|
||||
// Get loads the image from the file system.
|
||||
func (s FileSystem) Get(key string) []byte {
|
||||
content, err := ioutil.ReadFile(filepath.Join(s.cfg.RootDirectory, key))
|
||||
content, err := ioutil.ReadFile(filepath.Join(s.dir, key))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -24,11 +33,12 @@ func (s FileSystem) Get(key string) []byte {
|
||||
return content
|
||||
}
|
||||
|
||||
// Set writes the image to the file system.
|
||||
func (s FileSystem) Set(key string, img []byte) error {
|
||||
path := filepath.Join(s.cfg.RootDirectory, key)
|
||||
folder := filepath.Dir(path)
|
||||
if err := createFolderIfNotExists(folder); err != nil {
|
||||
return fmt.Errorf("error while creating folder %s", folder)
|
||||
path := filepath.Join(s.dir, key)
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return fmt.Errorf("error while creating directory %s", dir)
|
||||
}
|
||||
|
||||
f, err := os.Create(path)
|
||||
@@ -44,7 +54,15 @@ func (s FileSystem) Set(key string, img []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s FileSystem) BuildKey(ctx StorageContext) string {
|
||||
// BuildKey generate the unique key for a thumbnail.
|
||||
// The key is structure as follows:
|
||||
//
|
||||
// <first two letters of etag>/<next two letters of etag>/<rest of etag>/<width>x<height>.<filetype>
|
||||
//
|
||||
// e.g. 97/9f/4c8db98f7b82e768ef478d3c8612/500x300.png
|
||||
//
|
||||
// The key also represents the path to the thumbnail in the filesystem under the configured root directory.
|
||||
func (s FileSystem) BuildKey(ctx Context) string {
|
||||
etag := ctx.ETag
|
||||
filetype := ctx.Types[0]
|
||||
filename := strconv.Itoa(ctx.Width) + "x" + strconv.Itoa(ctx.Height) + "." + filetype
|
||||
@@ -60,13 +78,3 @@ func (s FileSystem) BuildKey(ctx StorageContext) string {
|
||||
|
||||
return key.String()
|
||||
}
|
||||
|
||||
func createFolderIfNotExists(folder string) error {
|
||||
if _, err := os.Stat(folder); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(folder, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package storage
|
||||
|
||||
type StorageContext struct {
|
||||
// Context combines different attributes needed for storage operations.
|
||||
type Context struct {
|
||||
ETag string
|
||||
Types []string
|
||||
Width int
|
||||
@@ -11,5 +12,5 @@ type StorageContext struct {
|
||||
type Storage interface {
|
||||
Get(string) []byte
|
||||
Set(string, []byte) error
|
||||
BuildKey(StorageContext) string
|
||||
BuildKey(Context) string
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@ package thumbnails
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"time"
|
||||
|
||||
"github.com/nfnt/resize"
|
||||
"github.com/owncloud/ocis-thumbnails/pkg/thumbnails/storage"
|
||||
)
|
||||
|
||||
// ThumbnailContext bundles information needed to generate a thumbnail for afile
|
||||
type ThumbnailContext struct {
|
||||
// Context bundles information needed to generate a thumbnail for afile
|
||||
type Context struct {
|
||||
Width int
|
||||
Height int
|
||||
ImagePath string
|
||||
@@ -21,8 +20,10 @@ type ThumbnailContext struct {
|
||||
// Manager is responsible for generating thumbnails
|
||||
type Manager interface {
|
||||
// Get will return a thumbnail for a file
|
||||
Get(ThumbnailContext, image.Image) ([]byte, error)
|
||||
GetStored(ThumbnailContext) []byte
|
||||
Get(Context, image.Image) ([]byte, error)
|
||||
// GetStored loads the thumbnail from the storage.
|
||||
// It will return nil if no image is stored for the given context.
|
||||
GetStored(Context) []byte
|
||||
}
|
||||
|
||||
// SimpleManager is a simple implementation of Manager
|
||||
@@ -31,7 +32,7 @@ type SimpleManager struct {
|
||||
}
|
||||
|
||||
// Get implements the Get Method of Manager
|
||||
func (s SimpleManager) Get(ctx ThumbnailContext, img image.Image) ([]byte, error) {
|
||||
func (s SimpleManager) Get(ctx Context, img image.Image) ([]byte, error) {
|
||||
thumbnail := s.generate(ctx, img)
|
||||
|
||||
key := s.Storage.BuildKey(mapToStorageContext(ctx))
|
||||
@@ -48,25 +49,19 @@ func (s SimpleManager) Get(ctx ThumbnailContext, img image.Image) ([]byte, error
|
||||
|
||||
// GetStored tries to get the stored thumbnail and return it.
|
||||
// If there is no cached thumbnail it will return nil
|
||||
func (s SimpleManager) GetStored(ctx ThumbnailContext) []byte {
|
||||
func (s SimpleManager) GetStored(ctx Context) []byte {
|
||||
key := s.Storage.BuildKey(mapToStorageContext(ctx))
|
||||
stored := s.Storage.Get(key)
|
||||
if stored == nil {
|
||||
return nil
|
||||
}
|
||||
return stored
|
||||
}
|
||||
|
||||
func (s SimpleManager) generate(ctx ThumbnailContext, img image.Image) image.Image {
|
||||
// TODO: remove, just for demo purposes
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
func (s SimpleManager) generate(ctx Context, img image.Image) image.Image {
|
||||
thumbnail := resize.Thumbnail(uint(ctx.Width), uint(ctx.Height), img, resize.Lanczos2)
|
||||
return thumbnail
|
||||
}
|
||||
|
||||
func mapToStorageContext(ctx ThumbnailContext) storage.StorageContext {
|
||||
sCtx := storage.StorageContext{
|
||||
func mapToStorageContext(ctx Context) storage.Context {
|
||||
sCtx := storage.Context{
|
||||
ETag: ctx.ETag,
|
||||
Width: ctx.Width,
|
||||
Height: ctx.Height,
|
||||
|
||||
Reference in New Issue
Block a user