|
|
|
@ -1,9 +1,19 @@ |
|
|
|
package rest |
|
|
|
|
|
|
|
import ( |
|
|
|
"net/http" |
|
|
|
"image" |
|
|
|
"os" |
|
|
|
"strconv" |
|
|
|
"github.com/disintegration/imaging" |
|
|
|
"net/url" |
|
|
|
) |
|
|
|
|
|
|
|
//@Service
|
|
|
|
type ImageCacheService struct { |
|
|
|
Bean |
|
|
|
imageCacheDao *ImageCacheDao |
|
|
|
userDao *UserDao |
|
|
|
} |
|
|
|
|
|
|
|
//初始化方法
|
|
|
|
@ -15,6 +25,11 @@ func (this *ImageCacheService) Init(context *Context) { |
|
|
|
this.imageCacheDao = b |
|
|
|
} |
|
|
|
|
|
|
|
b = context.GetBean(this.userDao) |
|
|
|
if b, ok := b.(*UserDao); ok { |
|
|
|
this.userDao = b |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。
|
|
|
|
@ -25,3 +40,133 @@ func (this *ImageCacheService) Detail(uuid string) *ImageCache { |
|
|
|
return imageCache |
|
|
|
} |
|
|
|
|
|
|
|
//图片预处理功能。
|
|
|
|
func (this *ImageCacheService) ResizeImage(request *http.Request, filePath string) *image.NRGBA { |
|
|
|
|
|
|
|
diskFile, err := os.Open(filePath) |
|
|
|
this.PanicError(err) |
|
|
|
defer diskFile.Close() |
|
|
|
|
|
|
|
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") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//单边缩略
|
|
|
|
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("单边缩略必须指定imageResizeW或imageResizeH") |
|
|
|
} |
|
|
|
} 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("固定宽高,自动裁剪 必须同时指定imageResizeW和imageResizeH") |
|
|
|
} |
|
|
|
} 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("强制宽高缩略必须同时指定imageResizeW和imageResizeH") |
|
|
|
} |
|
|
|
} else { |
|
|
|
panic("不支持" + imageResizeM + "处理模式") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//缓存一张处理完毕了的图片
|
|
|
|
func (this *ImageCacheService) cacheImage(writer http.ResponseWriter, request *http.Request, matter *Matter) *ImageCache { |
|
|
|
|
|
|
|
// 防止中文乱码
|
|
|
|
fileName := url.QueryEscape(matter.Name) |
|
|
|
|
|
|
|
//当前的文件是否是图片,只有图片才能处理。
|
|
|
|
extension := GetExtension(fileName) |
|
|
|
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, |
|
|
|
} |
|
|
|
|
|
|
|
format, ok := formats[extension] |
|
|
|
if !ok { |
|
|
|
panic("该图片格式不支持处理") |
|
|
|
} |
|
|
|
|
|
|
|
//resize图片
|
|
|
|
dstImage := this.ResizeImage(request, CONFIG.MatterPath+matter.Path) |
|
|
|
|
|
|
|
user := this.userDao.FindByUuid(matter.UserUuid) |
|
|
|
//获取文件应该存放在的物理路径的绝对路径和相对路径。
|
|
|
|
absolutePath, relativePath := GetUserFilePath(user.Username, true) |
|
|
|
absolutePath = absolutePath + "/" + fileName |
|
|
|
relativePath = relativePath + "/" + fileName |
|
|
|
|
|
|
|
fileWriter, err := os.Create(absolutePath) |
|
|
|
this.PanicError(err) |
|
|
|
defer fileWriter.Close() |
|
|
|
|
|
|
|
//处理后的图片存放在本地
|
|
|
|
err = imaging.Encode(fileWriter, dstImage, format) |
|
|
|
this.PanicError(err) |
|
|
|
|
|
|
|
//获取新文件的大小
|
|
|
|
fileInfo, err := fileWriter.Stat() |
|
|
|
this.PanicError(err) |
|
|
|
|
|
|
|
//相关信息写到缓存中去
|
|
|
|
imageCache := &ImageCache{ |
|
|
|
UserUuid: matter.UserUuid, |
|
|
|
MatterUuid: matter.Uuid, |
|
|
|
Uri: request.RequestURI, |
|
|
|
Size: fileInfo.Size(), |
|
|
|
Path: relativePath, |
|
|
|
} |
|
|
|
this.imageCacheDao.Create(imageCache) |
|
|
|
|
|
|
|
return imageCache |
|
|
|
} |
|
|
|
|