tank/rest/matter_service.go
2018-07-02 20:41:56 +08:00

255 lines
6.5 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 rest
import (
"io"
"mime/multipart"
"os"
"regexp"
"strings"
"net/http"
"github.com/disintegration/imaging"
"strconv"
)
//@Service
type MatterService struct {
Bean
matterDao *MatterDao
}
//初始化方法
func (this *MatterService) Init(context *Context) {
//手动装填本实例的Bean. 这里必须要用中间变量方可。
b := context.GetBean(this.matterDao)
if b, ok := b.(*MatterDao); ok {
this.matterDao = b
}
}
//根据一个文件夹路径找到最后一个文件夹的uuid如果中途出错返回err.
func (this *MatterService) GetDirUuid(userUuid string, dir string) string {
if dir == "" {
panic(`文件夹不能为空`)
} else if dir[0:1] != "/" {
panic(`文件夹必须以/开头`)
} else if strings.Index(dir, "//") != -1 {
panic(`文件夹不能出现连续的//`)
} else if m, _ := regexp.MatchString(`[<>|*?\\]`, dir); m {
panic(`文件夹中不能包含以下特殊符号:< > | * ? \`)
}
if dir == "/" {
return "root"
}
if dir[len(dir)-1] == '/' {
dir = dir[:len(dir)-1]
}
//递归找寻文件的上级目录uuid.
folders := strings.Split(dir, "/")
if len(folders) > 32 {
panic("文件夹最多32层。")
}
puuid := "root"
for k, name := range folders {
if len(name) > 200 {
panic("每级文件夹的最大长度为200")
}
if k == 0 {
continue
}
matter := this.matterDao.FindByUserUuidAndPuuidAndNameAndDirTrue(userUuid, puuid, name)
if matter == nil {
//创建一个文件夹。这里一般都是通过alien接口来创建的文件夹。
matter = &Matter{
Puuid: puuid,
UserUuid: userUuid,
Dir: true,
Alien: true,
Name: name,
}
matter = this.matterDao.Create(matter)
}
puuid = matter.Uuid
}
return puuid
}
//获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。
func (this *MatterService) Detail(uuid string) *Matter {
matter := this.matterDao.CheckByUuid(uuid)
//组装file的内容展示其父组件。
puuid := matter.Puuid
tmpMatter := matter
for puuid != "root" {
pFile := this.matterDao.CheckByUuid(puuid)
tmpMatter.Parent = pFile
tmpMatter = pFile
puuid = pFile.Puuid
}
return matter
}
//开始上传文件
//上传文件. alien表明文件是否是应用使用的文件。
func (this *MatterService) Upload(file multipart.File, user *User, puuid string, filename string, privacy bool, alien bool) *Matter {
//文件名不能太长。
if len(filename) > 200 {
panic("文件名不能超过200")
}
//获取文件应该存放在的物理路径的绝对路径和相对路径。
absolutePath, relativePath := GetUserFilePath(user.Username)
absolutePath = absolutePath + "/" + filename
relativePath = relativePath + "/" + filename
distFile, err := os.OpenFile(absolutePath, os.O_WRONLY|os.O_CREATE, 0777)
this.PanicError(err)
defer distFile.Close()
written, err := io.Copy(distFile, file)
this.PanicError(err)
//判断用户自身上传大小的限制。
if user.SizeLimit >= 0 {
if written > user.SizeLimit {
panic("您最大只能上传" + HumanFileSize(user.SizeLimit) + "的文件")
}
}
//查找文件夹下面是否有同名文件。
matters := this.matterDao.ListByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, false, filename)
//如果有同名的文件,那么我们直接覆盖同名文件。
for _, dbFile := range matters {
this.matterDao.Delete(dbFile)
}
//将文件信息存入数据库中。
matter := &Matter{
Puuid: puuid,
UserUuid: user.Uuid,
Dir: false,
Alien: alien,
Name: filename,
Md5: "",
Size: written,
Privacy: privacy,
Path: relativePath,
}
matter = this.matterDao.Create(matter)
return matter
}
//处理图片下载功能。
func (this *MatterService) ResizeImage(writer http.ResponseWriter, request *http.Request, matter *Matter, diskFile *os.File) {
//当前的文件是否是图片,只有图片才能处理。
extension := 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,
}
format, ok := formats[extension]
if !ok {
panic("该图片格式不支持处理")
}
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)
dst := imaging.Resize(src, imageResizeW, 0, imaging.Lanczos)
err = imaging.Encode(writer, dst, format)
this.PanicError(err)
} else if imageResizeH > 0 {
//将图缩略成高度为100宽度按比例处理。
src, err := imaging.Decode(diskFile)
this.PanicError(err)
dst := imaging.Resize(src, 0, imageResizeH, imaging.Lanczos)
err = imaging.Encode(writer, dst, format)
this.PanicError(err)
} else {
panic("单边缩略必须指定imageResizeW或imageResizeH")
}
} else if imageResizeM == "fill" {
//固定宽高,自动裁剪
if imageResizeW > 0 && imageResizeH > 0 {
src, err := imaging.Decode(diskFile)
this.PanicError(err)
dst := imaging.Fill(src, imageResizeW, imageResizeH, imaging.Center, imaging.Lanczos)
err = imaging.Encode(writer, dst, format)
this.PanicError(err)
} else {
panic("固定宽高,自动裁剪 必须同时指定imageResizeW和imageResizeH")
}
} else if imageResizeM == "fixed" {
//强制宽高缩略
if imageResizeW > 0 && imageResizeH > 0 {
src, err := imaging.Decode(diskFile)
this.PanicError(err)
dst := imaging.Resize(src, imageResizeW, imageResizeH, imaging.Lanczos)
err = imaging.Encode(writer, dst, format)
this.PanicError(err)
} else {
panic("强制宽高缩略必须同时指定imageResizeW和imageResizeH")
}
}
}