tank/code/image_cache_service.go
2019-04-26 02:59:35 +08:00

245 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package code
import (
"fmt"
"github.com/disintegration/imaging"
"image"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"tank/code/tool"
)
//@Service
type ImageCacheService struct {
Bean
imageCacheDao *ImageCacheDao
userDao *UserDao
matterDao *MatterDao
}
//初始化方法
func (this *ImageCacheService) Init() {
this.Bean.Init()
//手动装填本实例的Bean. 这里必须要用中间变量方可。
b := CONTEXT.GetBean(this.imageCacheDao)
if b, ok := b.(*ImageCacheDao); ok {
this.imageCacheDao = b
}
b = CONTEXT.GetBean(this.userDao)
if b, ok := b.(*UserDao); ok {
this.userDao = b
}
b = CONTEXT.GetBean(this.matterDao)
if b, ok := b.(*MatterDao); ok {
this.matterDao = b
}
}
//获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。
func (this *ImageCacheService) Detail(uuid string) *ImageCache {
imageCache := this.imageCacheDao.CheckByUuid(uuid)
return imageCache
}
//获取预处理时必要的参数
func (this *ImageCacheService) ResizeParams(request *http.Request) (needProcess bool, resizeMode string, resizeWidth int, resizeHeight int) {
var err error
//1.0 模式准备逐步废弃掉
if request.FormValue("imageProcess") == "resize" {
//老模式使用 imageResizeM,imageResizeW,imageResizeH
imageResizeM := request.FormValue("imageResizeM")
if imageResizeM == "" {
imageResizeM = "fit"
} else if imageResizeM != "fit" && imageResizeM != "fill" && imageResizeM != "fixed" {
panic("imageResizeM参数错误")
}
imageResizeWStr := request.FormValue("imageResizeW")
var imageResizeW int
if imageResizeWStr != "" {
imageResizeW, err = strconv.Atoi(imageResizeWStr)
this.PanicError(err)
if imageResizeW < 1 || imageResizeW > 4096 {
panic("缩放尺寸不能超过4096")
}
}
imageResizeHStr := request.FormValue("imageResizeH")
var imageResizeH int
if imageResizeHStr != "" {
imageResizeH, err = strconv.Atoi(imageResizeHStr)
this.PanicError(err)
if imageResizeH < 1 || imageResizeH > 4096 {
panic("缩放尺寸不能超过4096")
}
}
return true, imageResizeM, imageResizeW, imageResizeH
} else if request.FormValue("ir") != "" {
//新模式使用 mode_w_h 如果w或者h为0表示这项值不设置
imageResizeStr := request.FormValue("ir")
arr := strings.Split(imageResizeStr, "_")
if len(arr) != 3 {
panic("参数不符合规范格式要求为mode_w_h")
}
imageResizeM := arr[0]
if imageResizeM == "" {
imageResizeM = "fit"
} else if imageResizeM != "fit" && imageResizeM != "fill" && imageResizeM != "fixed" {
panic("imageResizeM参数错误")
}
imageResizeWStr := arr[1]
var imageResizeW int
if imageResizeWStr != "" {
imageResizeW, err = strconv.Atoi(imageResizeWStr)
this.PanicError(err)
if imageResizeW < 0 || imageResizeW > 4096 {
panic("缩放尺寸不能超过4096")
}
}
imageResizeHStr := arr[2]
var imageResizeH int
if imageResizeHStr != "" {
imageResizeH, err = strconv.Atoi(imageResizeHStr)
this.PanicError(err)
if imageResizeH < 0 || imageResizeH > 4096 {
panic("缩放尺寸不能超过4096")
}
}
return true, imageResizeM, imageResizeW, imageResizeH
} else {
return false, "", 0, 0
}
}
//图片预处理功能。
func (this *ImageCacheService) ResizeImage(request *http.Request, filePath string) *image.NRGBA {
diskFile, err := os.Open(filePath)
this.PanicError(err)
defer func() {
e := diskFile.Close()
this.PanicError(e)
}()
_, imageResizeM, imageResizeW, imageResizeH := this.ResizeParams(request)
//单边缩略
if imageResizeM == "fit" {
//将图缩略成宽度为100高度按比例处理。
if imageResizeW != 0 {
src, err := imaging.Decode(diskFile)
this.PanicError(err)
return imaging.Resize(src, imageResizeW, 0, imaging.Lanczos)
} else if imageResizeH != 0 {
//将图缩略成高度为100宽度按比例处理。
src, err := imaging.Decode(diskFile)
this.PanicError(err)
return imaging.Resize(src, 0, imageResizeH, imaging.Lanczos)
} else {
panic("单边缩略必须指定宽或者高")
}
} else if imageResizeM == "fill" {
//固定宽高,自动裁剪
if imageResizeW > 0 && imageResizeH > 0 {
src, err := imaging.Decode(diskFile)
this.PanicError(err)
return imaging.Fill(src, imageResizeW, imageResizeH, imaging.Center, imaging.Lanczos)
} else {
panic("固定宽高,自动裁剪 必须同时指定宽和高")
}
} else if imageResizeM == "fixed" {
//强制宽高缩略
if imageResizeW > 0 && imageResizeH > 0 {
src, err := imaging.Decode(diskFile)
this.PanicError(err)
return imaging.Resize(src, imageResizeW, imageResizeH, imaging.Lanczos)
} else {
panic("强制宽高缩略必须同时指定宽和高")
}
} else {
panic("不支持" + imageResizeM + "处理模式")
}
}
//缓存一张图片
func (this *ImageCacheService) cacheImage(writer http.ResponseWriter, request *http.Request, matter *Matter) *ImageCache {
//当前的文件是否是图片,只有图片才能处理。
extension := tool.GetExtension(matter.Name)
formats := map[string]imaging.Format{
".jpg": imaging.JPEG,
".jpeg": imaging.JPEG,
".png": imaging.PNG,
".tif": imaging.TIFF,
".tiff": imaging.TIFF,
".bmp": imaging.BMP,
".gif": imaging.GIF,
}
_, imageResizeM, imageResizeW, imageResizeH := this.ResizeParams(request)
mode := fmt.Sprintf("%s_%d_%d", imageResizeM, imageResizeW, imageResizeH)
format, ok := formats[extension]
if !ok {
panic("该图片格式不支持处理")
}
user := this.userDao.FindByUuid(matter.UserUuid)
//resize图片
dstImage := this.ResizeImage(request, matter.AbsolutePath())
cacheImageName := tool.GetSimpleFileName(matter.Name) + "_" + mode + extension
cacheImageRelativePath := tool.GetSimpleFileName(matter.Path) + "_" + mode + extension
cacheImageAbsolutePath := GetUserCacheRootDir(user.Username) + tool.GetSimpleFileName(matter.Path) + "_" + mode + extension
//创建目录。
dir := filepath.Dir(cacheImageAbsolutePath)
tool.MakeDirAll(dir)
fileWriter, err := os.Create(cacheImageAbsolutePath)
this.PanicError(err)
defer func() {
e := fileWriter.Close()
this.PanicError(e)
}()
//处理后的图片存放在本地
err = imaging.Encode(fileWriter, dstImage, format)
this.PanicError(err)
//获取新文件的大小
fileInfo, err := fileWriter.Stat()
this.PanicError(err)
//相关信息写到缓存中去
imageCache := &ImageCache{
Name: cacheImageName,
UserUuid: matter.UserUuid,
Username: user.Username,
MatterUuid: matter.Uuid,
MatterName: matter.Name,
Mode: mode,
Size: fileInfo.Size(),
Path: cacheImageRelativePath,
}
this.imageCacheDao.Create(imageCache)
return imageCache
}