media

package module
v0.0.0-...-6a72910 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 6, 2021 License: MIT Imports: 31 Imported by: 0

README

Media Library

Media is a Golang library that supports the upload of files/images/videos to a filesystem or cloud storage as well as linked videos (i.e. YouTube, Vimeo, etc.). The plugin includes:

  • cropping and resizing features for images.
  • optional multiple sizes for each media resource.
  • Accessibility helpers.

GoDoc

File Types

Media accepts any and every file type, yet it associates certain file types as images or videos so as to provide helpers supporting those media's specific needs.

Images: .jpg, .jpeg, .png, .tif, .tiff, .bmp, .gif

Videos: .mp4, .m4p, .m4v, .m4v, .mov, .mpeg, .webm, .avi, .ogg, .ogv

Usage

Media depends on GORM models as it is using GORM's callbacks to handle file processing, so you will need to register callbacks first:

import (
  "github.com/jinzhu/gorm"
  "github.com/qor/media"
)

DB, err = gorm.Open("sqlite3", "demo_db") // [gorm](https://github.com/jinzhu/gorm)

media.RegisterCallbacks(DB)

Then add OSS(Object Storage Service) to your model:

import (
  "github.com/jinzhu/gorm"
  "github.com/qor/media/oss"
)

type Product struct {
  gorm.Model
  Image oss.OSS
}

Last, configure the storage. The default value is oss.Storage := filesystem.New("public"). Here we configure S3 as storage.

import (
  // "github.com/oss/filesystem"
  "github.com/oss/s3"
)

oss.Storage := s3.New(s3.Config{AccessID: "access_id", AccessKey: "access_key", Region: "region", Bucket: "bucket", Endpoint: "cdn.getqor.com", ACL: aws.BucketCannedACLPublicRead})
// Default configuration `oss.Storage := filesystem.New("public")`

Operate stored files

The OSS(Object Storage Service) provides a pretty simple API to operate files on filesytem or cloud storage

type StorageInterface interface {
  Get(path string) (*os.File, error)
  GetStream(path string) (io.ReadCloser, error)
  Put(path string, reader io.Reader) (*Object, error)
  Delete(path string) error
  List(path string) ([]*Object, error)
  GetEndpoint() string
  GetURL(path string) (string, error)
}

So once you finished the setting, you could operate saved files like this:

storage := s3.New(s3.Config{AccessID: "access_id", AccessKey: "access_key", Region: "region", Bucket: "bucket", Endpoint: "cdn.getqor.com", ACL: aws.BucketCannedACLPublicRead})
// storage := filesystem.New("public")

// Save a reader interface into storage
storage.Put("/sample.txt", reader)

// Get file with path
storage.Get("/sample.txt")

// Delete file with path
storage.Delete("/sample.txt")

// List all objects under path
storage.List("/")

Predefine common image size

You can implement the GetSizes function to predefine image sizes. The size name can be used to fetch image of corresponding size.

import (
  "github.com/qor/media/oss"
  "github.com/jinzhu/gorm"
)

type Product struct {
  gorm.Model
  Image ProductIconImageStorage
}

type ProductIconImageStorage struct{
  oss.OSS
}

func (ProductIconImageStorage) GetSizes() map[string]*media.Size {
  return map[string]*media.Size{
    // Add padding to thumbnail if ratio doesn't match, by default, crop center
    "small":    {Width: 60 * 2, Height: 60 * 2, Padding: true},
    "small@ld": {Width: 60, Height: 60},

    "middle":    {Width: 108 * 2, Height: 108 * 2},
    "middle@ld": {Width: 108, Height: 108},

    "big":    {Width: 144 * 2, Height: 144 * 2},
    "big@ld": {Width: 144, Height: 144},
  }
}

// Get image's url with style
product.Image.URL("small")
product.Image.URL("big@ld")

How to setup a Media Library and use media box

You can also setup a media library, not use oss.OSS in model directly, then you can choose file from media library.

setup a media library

import(
"github.com/saitofun/qor-admin"
"github.com/qor/media/oss"
"github.com/oss/s3"
"github.com/qor/media/media_library"
)

db.AutoMigrate(&media_library.MediaLibrary{})
adm = admin.New(&admin.AdminConfig{SiteName: "XXX", DB: db})
oss.Storage = s3.New(s3.Config{AccessID: "access_id", AccessKey: "access_key", Region: "region", Bucket: "bucket", Endpoint: "cdn.getqor.com", ACL: aws.BucketCannedACLPublicRead})
adm.AddResource(&media_library.MediaLibrary{}, &admin.Config{Name: "Media Library")
media.RegisterCallbacks(db)

use media box in model

import(
"github.com/qor/media/media_library"
"github.com/qor/media
}

type Product struct {
	gorm.Model

	Image          media_library.MediaBox
}

   res :=adm.AddResource(&Product{}, &admin.Config{Name: "Product")
   res.Meta(&admin.Meta{Name: "Image", Config: &media_library.MediaBoxConfig{
		Max:                1,
		Sizes:              map[string]*media.Size{
	        "m": {Width: 500,Height:500},
        },
		AllowType:          media_library.ALLOW_TYPE_IMAGE,
	}})

Set file storage path in the file system

The default size and path for Image. The default size is 4294967295 and default path is {repo_path}/public/system/{{class}}/{{primary_key}}/{{column}}.{{extension}}.

You can set the path and size manually by adding tag to the field like this:

type Product struct {
  gorm.Model
  Image oss.OSS `sql:"size:4294967295;" media_library:"url:/backend/{{class}}/{{primary_key}}/{{column}}.{{extension}};path:./private"`
}

The media takes two parameters, url and path. the url set the relative file path and the path set the prefix path. So suppose we uploaded a image called demo.png. The file will be stored at {repo_path}/private/backend/products/1/demo.png.

Be careful when using http.FileServer

The http.FileServer not only serves the files, but also shows the directory contents. This is very dangerous when you do things like

for _, path := range []string{"system", "javascripts", "stylesheets", "images"} {
  mux.Handle(fmt.Sprintf("/%s/", path), http.FileServer(http.Dir("public")))
}

The files under public will be exposed to public(especially the search engine!), Imagine someone upload a illegal or sensitive file to your server. The directory is fully visible to everyone and its indexable by search engines and boom!

To avoid this problem, we made a safer FileServer function here. This function serves file only. So the previous code now turned into:

for _, path := range []string{"system", "javascripts", "stylesheets", "images"} {
  mux.Handle(fmt.Sprintf("/%s/", path), utils.FileServer(http.Dir("public")))
}

Accessibility helpers

Media Library has some features aimed at helping achieve Accessibile frontends:

  • capture of a textual description for images, videos, and linked videos to aid with Accessibility.
  • capture of textual transcript for videos and linked videos to aid with Accessibility.

The values captured are fed into the sub-templates for each media type to be used if/where necessary. For example, an image's HTML output (an img tag) manifests the textual description within an alt attribute while a video's HTML (an iframe tag) manifests the textual description within a title attribute.

License

Released under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// set MediaLibraryURL to change the default url /system/{{class}}/{{primary_key}}/{{column}}.{{extension}}
	MediaLibraryURL = ""
)

Functions

func GetImageFormat

func GetImageFormat(url string) (*imaging.Format, error)

func IsImageFormat

func IsImageFormat(name string) bool

IsImageFormat check filename is image or not

func IsSVGFormat

func IsSVGFormat(name string) bool

func IsVideoFormat

func IsVideoFormat(name string) bool

IsVideoFormat check filename is video or not

func RegisterCallbacks

func RegisterCallbacks(db *gorm.DB)

RegisterCallbacks register callback into GORM DB

func RegisterMediaHandler

func RegisterMediaHandler(name string, handler MediaHandler)

RegisterMediaHandler register Media library handler

Types

type Base

type Base struct {
	FileName    string
	Url         string
	CropOptions map[string]*CropOption `json:",omitempty"`
	Delete      bool                   `json:"-"`
	Crop        bool                   `json:"-"`
	FileHeader  FileHeader             `json:"-"`
	Reader      io.Reader              `json:"-"`
	Options     map[string]string      `json:",omitempty"`
	// contains filtered or unexported fields
}

Base defined a base struct for storages

func (Base) ConfigureQorMetaBeforeInitialize

func (Base) ConfigureQorMetaBeforeInitialize(meta resource.Metaor)

ConfigureQorMetaBeforeInitialize configure this field for Qor Admin

func (*Base) Cropped

func (b *Base) Cropped(values ...bool) (result bool)

Cropped mark the image to be cropped

func (Base) Ext

func (b Base) Ext() string

func (*Base) GetCropOption

func (b *Base) GetCropOption(name string) *image.Rectangle

GetCropOption get crop options

func (Base) GetFileHeader

func (b Base) GetFileHeader() FileHeader

GetFileHeader get file's header, this value only exists when saving files

func (Base) GetFileName

func (b Base) GetFileName() string

GetFileName get file's name

func (Base) GetSizes

func (b Base) GetSizes() map[string]*Size

GetSizes get configured sizes, it will be used to crop images accordingly

func (Base) GetURL

func (b Base) GetURL(option *Option, scope *gorm.Scope, field *gorm.Field, templater URLTemplater) string

GetURL get default URL for a model based on its options

func (Base) GetURLTemplate

func (b Base) GetURLTemplate(option *Option) (path string)

GetURLTemplate get url template

func (Base) IsImage

func (b Base) IsImage() bool

IsImage return if it is an image

func (Base) IsSVG

func (b Base) IsSVG() bool

func (Base) IsVideo

func (b Base) IsVideo() bool

func (*Base) NeedCrop

func (b *Base) NeedCrop() bool

NeedCrop return the file needs to be cropped or not

func (Base) Retrieve

func (b Base) Retrieve(url string) (*os.File, error)

Retrieve retrieve file content with url

func (*Base) Scan

func (b *Base) Scan(data interface{}) (err error)

Scan scan files, crop options, db values into struct

func (Base) String

func (b Base) String() string

String return file's url

func (Base) URL

func (b Base) URL(styles ...string) string

URL return file's url with given style

func (Base) Value

func (b Base) Value() (driver.Value, error)

Value return struct's Value

type CropOption

type CropOption struct {
	X, Y, Width, Height int
}

CropOption includes crop options

type FileHeader

type FileHeader interface {
	Open() (multipart.File, error)
}

FileHeader is an interface, for matched values, when call its `Open` method will return `multipart.File`

type FileInterface

type FileInterface interface {
	io.ReadSeeker
	io.Closer
}

FileInterface media file interface

type Media

type Media interface {
	Scan(value interface{}) error
	Value() (driver.Value, error)

	GetURLTemplate(*Option) string
	GetURL(option *Option, scope *gorm.Scope, field *gorm.Field, templater URLTemplater) string

	GetFileHeader() FileHeader
	GetFileName() string

	GetSizes() map[string]*Size
	NeedCrop() bool
	Cropped(values ...bool) bool
	GetCropOption(name string) *image.Rectangle

	Store(url string, option *Option, reader io.Reader) error
	Retrieve(url string) (FileInterface, error)

	IsImage() bool

	URL(style ...string) string
	Ext() string
	String() string
}

Media is an interface including methods that needs for a media library storage

type MediaHandler

type MediaHandler interface {
	CouldHandle(media Media) bool
	Handle(media Media, file FileInterface, option *Option) error
}

MediaHandler media library handler interface, defined which files could be handled, and the handler

type Option

type Option map[string]string

Option media library option

func (Option) Get

func (option Option) Get(key string) string

get option with name

func (Option) Set

func (option Option) Set(key string, val string)

set option

type Size

type Size struct {
	Width   int
	Height  int
	Padding bool
}

Size is a struct, used for `GetSizes` method, it will return a slice of Size, media library will crop images automatically based on it

type URLTemplater

type URLTemplater interface {
	GetURLTemplate(*Option) string
}

URLTemplater is a interface to return url template

Directories

Path Synopsis
handlers

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL