diff --git a/rest/alien_controller.go b/rest/alien_controller.go index 5385fcb..796a0f7 100644 --- a/rest/alien_controller.go +++ b/rest/alien_controller.go @@ -59,7 +59,6 @@ func (this *AlienController) Init() { if c, ok := b.(*AlienService); ok { this.alienService = c } - } //注册自己的路由。 @@ -199,7 +198,7 @@ func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, reques dir := request.FormValue("dir") user := this.CheckRequestUser(writer, request) - dirUuid := this.matterService.GetDirUuid(user.Uuid, dir) + dirUuid, _ := this.matterService.GetDirUuid(user, dir) mm, _ := time.ParseDuration(fmt.Sprintf("%ds", expire)) uploadToken := &UploadToken{ @@ -261,10 +260,15 @@ func (this *AlienController) Upload(writer http.ResponseWriter, request *http.Re user := this.userDao.CheckByUuid(uploadToken.UserUuid) - request.ParseMultipartForm(32 << 20) + err := request.ParseMultipartForm(32 << 20) + this.PanicError(err) + file, handler, err := request.FormFile("file") this.PanicError(err) - defer file.Close() + defer func() { + e := file.Close() + this.PanicError(e) + }() if handler.Filename != uploadToken.Filename { panic("文件名称不正确") @@ -312,7 +316,17 @@ func (this *AlienController) CrawlToken(writer http.ResponseWriter, request *htt panic("资源url必填,并且应该以http://或者https://开头") } - matter := this.matterService.Crawl(url, uploadToken.Filename, user, uploadToken.FolderUuid, uploadToken.Privacy) + var dirPath string + if uploadToken.FolderUuid == MATTER_ROOT { + + dirPath = "/" + } else { + + dirMatter := this.matterDao.CheckByUuid(uploadToken.FolderUuid) + dirPath = dirMatter.Path + } + + matter := this.matterService.Crawl(url, uploadToken.Filename, user, uploadToken.FolderUuid, dirPath, uploadToken.Privacy) //更新这个uploadToken的信息. uploadToken.ExpireTime = time.Now() @@ -355,9 +369,9 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht //文件夹路径,以 / 开头。 dir := request.FormValue("dir") user := this.CheckRequestUser(writer, request) - dirUuid := this.matterService.GetDirUuid(user.Uuid, dir) + dirUuid, dirRelativePath := this.matterService.GetDirUuid(user, dir) - matter := this.matterService.Crawl(url, filename, user, dirUuid, privacy) + matter := this.matterService.Crawl(url, filename, user, dirUuid, dirRelativePath, privacy) return this.Success(matter) } @@ -412,11 +426,11 @@ func (this *AlienController) FetchDownloadToken(writer http.ResponseWriter, requ //预览一个文件。既可以使用登录的方式,也可以使用授权的方式 func (this *AlienController) Preview(writer http.ResponseWriter, request *http.Request, uuid string, filename string) { - this.alienService.PreviewOrDownload(writer, request, uuid, filename, false) + this.alienService.PreviewOrDownload(writer, request, uuid, filename, false) } //下载一个文件。既可以使用登录的方式,也可以使用授权的方式 func (this *AlienController) Download(writer http.ResponseWriter, request *http.Request, uuid string, filename string) { - this.alienService.PreviewOrDownload(writer, request, uuid, filename, true) + this.alienService.PreviewOrDownload(writer, request, uuid, filename, true) } diff --git a/rest/base_model.go b/rest/base_model.go index 5dfbe47..65c9395 100644 --- a/rest/base_model.go +++ b/rest/base_model.go @@ -38,7 +38,7 @@ func (this *Base) Map() map[string]interface{} { return data } -func (Base) TableName() string { +func (this *Base) TableName() string { return TABLE_PREFIX + "base" } diff --git a/rest/dashboard_model.go b/rest/dashboard_model.go index ec8b647..0acecc5 100644 --- a/rest/dashboard_model.go +++ b/rest/dashboard_model.go @@ -18,7 +18,7 @@ type Dashboard struct { } // set File's table name to be `profiles` -func (Dashboard) TableName() string { +func (this *Dashboard) TableName() string { return TABLE_PREFIX + "dashboard" } diff --git a/rest/download_token_model.go b/rest/download_token_model.go index c4b9f3f..f572f4c 100644 --- a/rest/download_token_model.go +++ b/rest/download_token_model.go @@ -12,6 +12,6 @@ type DownloadToken struct { Ip string `json:"ip" gorm:"type:varchar(128) not null"` } -func (DownloadToken) TableName() string { +func (this *DownloadToken) TableName() string { return TABLE_PREFIX + "download_token" } diff --git a/rest/footprint_model.go b/rest/footprint_model.go index 1751da1..8dc7984 100644 --- a/rest/footprint_model.go +++ b/rest/footprint_model.go @@ -15,6 +15,6 @@ type Footprint struct { } // set File's table name to be `profiles` -func (Footprint) TableName() string { +func (this *Footprint) TableName() string { return TABLE_PREFIX + "footprint" } diff --git a/rest/image_cache_model.go b/rest/image_cache_model.go index 74cb1e7..6066891 100644 --- a/rest/image_cache_model.go +++ b/rest/image_cache_model.go @@ -15,6 +15,6 @@ type ImageCache struct { } // set File's table name to be `profiles` -func (ImageCache) TableName() string { +func (this *ImageCache) TableName() string { return TABLE_PREFIX + "image_cache" } diff --git a/rest/image_cache_service.go b/rest/image_cache_service.go index b23a554..407199e 100644 --- a/rest/image_cache_service.go +++ b/rest/image_cache_service.go @@ -168,7 +168,7 @@ func (this *ImageCacheService) ResizeImage(request *http.Request, filePath strin } } -//缓存一张处理完毕了的图片 +//缓存一张图片 func (this *ImageCacheService) cacheImage(writer http.ResponseWriter, request *http.Request, matter *Matter) *ImageCache { //当前的文件是否是图片,只有图片才能处理。 @@ -183,21 +183,22 @@ func (this *ImageCacheService) cacheImage(writer http.ResponseWriter, request *h ".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("该图片格式不支持处理") } - //resize图片 - dstImage := this.ResizeImage(request, CONFIG.MatterPath+matter.Path) - user := this.userDao.FindByUuid(matter.UserUuid) - //获取文件应该存放在的物理路径的绝对路径和相对路径。 - absolutePath, relativePath := GetUserFileDir(user.Username, true) - absolutePath = absolutePath + "/" + matter.Name - relativePath = relativePath + "/" + matter.Name - fileWriter, err := os.Create(absolutePath) + //resize图片 + dstImage := this.ResizeImage(request, GetUserCacheRootDir(user.Username)+matter.Path) + + cacheImagePath := GetSimpleFileName(matter.Path) + "_" + mode + extension + + fileWriter, err := os.Create(cacheImagePath) this.PanicError(err) defer func() { e := fileWriter.Close() @@ -212,15 +213,13 @@ func (this *ImageCacheService) cacheImage(writer http.ResponseWriter, request *h fileInfo, err := fileWriter.Stat() this.PanicError(err) - _, imageResizeM, imageResizeW, imageResizeH := this.ResizeParams(request) - //相关信息写到缓存中去 imageCache := &ImageCache{ UserUuid: matter.UserUuid, MatterUuid: matter.Uuid, - Mode: fmt.Sprintf("%s_%d_%d", imageResizeM, imageResizeW, imageResizeH), + Mode: mode, Size: fileInfo.Size(), - Path: relativePath, + Path: cacheImagePath, } this.imageCacheDao.Create(imageCache) diff --git a/rest/install_controller.go b/rest/install_controller.go index 61a97d9..a52377d 100644 --- a/rest/install_controller.go +++ b/rest/install_controller.go @@ -188,7 +188,7 @@ func (this *InstallController) getTableMeta(gormDb *gorm.DB, entity IBase) (bool //根据表名获取建表SQL语句 func (this *InstallController) getTableMetaList(db *gorm.DB) []*InstallTableInfo { - var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, UploadToken{}, &User{}} + var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, &UploadToken{}, &User{}} var installTableInfos []*InstallTableInfo for _, iBase := range tableNames { @@ -250,7 +250,7 @@ func (this *InstallController) TableInfoList(writer http.ResponseWriter, request //创建缺失数据库和表 func (this *InstallController) CreateTable(writer http.ResponseWriter, request *http.Request) *WebResult { - var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, UploadToken{}, &User{}} + var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, &UploadToken{}, &User{}} var installTableInfos []*InstallTableInfo db := this.openDbConnection(writer, request) diff --git a/rest/matter_controller.go b/rest/matter_controller.go index d37eb5a..cefe15c 100644 --- a/rest/matter_controller.go +++ b/rest/matter_controller.go @@ -116,7 +116,14 @@ func (this *MatterController) CreateDirectory(writer http.ResponseWriter, reques panic("puuid必填") } - path := fmt.Sprintf("/%s/%s", user.Username, name) + //判断同级文件夹中是否有同名的文件。 + count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, true, name) + + if count > 0 { + this.PanicBadRequest("【" + name + "】已经存在了,请使用其他名称。") + } + + path := fmt.Sprintf("/%s", name) if puuid != MATTER_ROOT { //验证目标文件夹存在。 this.matterDao.CheckByUuidAndUserUuid(puuid, user.Uuid) @@ -139,21 +146,15 @@ func (this *MatterController) CreateDirectory(writer http.ResponseWriter, reques } } - //判断同级文件夹中是否有同名的文件。 - count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, true, name) - - if count > 0 { - this.PanicBadRequest("【" + name + "】已经存在了,请使用其他名称。") - } - //磁盘中创建文件夹。 - dirPath := MakeDirAll(CONFIG.MatterPath + path) + dirPath := MakeDirAll(GetUserFileRootDir(user.Username) + path) this.logger.Info("Create Directory: %s", dirPath) //数据库中创建文件夹。 matter := &Matter{ Puuid: puuid, UserUuid: user.Uuid, + Username: user.Username, Dir: true, Name: name, Path: path, @@ -264,15 +265,6 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R } user = this.userDao.CheckByUuid(userUuid) - if puuid == "" { - this.PanicBadRequest("puuid必填") - } else { - if puuid != MATTER_ROOT { - //验证puuid是否存在 - this.matterDao.CheckByUuidAndUserUuid(puuid, userUuid) - } - } - privacy := privacyStr == TRUE err = request.ParseMultipartForm(32 << 20) @@ -310,12 +302,16 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re user = this.userDao.CheckByUuid(userUuid) puuid := request.FormValue("puuid") + var dirRelativePath string if puuid == "" { this.PanicBadRequest("puuid必填") } else { - if puuid != MATTER_ROOT { + if puuid == MATTER_ROOT { + dirRelativePath = "" + } else { //找出上一级的文件夹。 - this.matterDao.CheckByUuidAndUserUuid(puuid, userUuid) + dirMatter := this.matterDao.CheckByUuidAndUserUuid(puuid, userUuid) + dirRelativePath = dirMatter.Path } } @@ -335,7 +331,7 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re panic("文件名必传") } - matter := this.matterService.Crawl(url, filename, user, puuid, privacy) + matter := this.matterService.Crawl(url, filename, user, puuid, dirRelativePath, privacy) return this.Success(matter) } diff --git a/rest/matter_model.go b/rest/matter_model.go index c36fd01..d23044c 100644 --- a/rest/matter_model.go +++ b/rest/matter_model.go @@ -1,8 +1,8 @@ package rest const ( - MATTER_ROOT = "root" - MATTER_CACHE = "cache" + MATTER_ROOT = "root" + MATTER_CACHE = "cache" ) /** @@ -12,6 +12,7 @@ type Matter struct { Base Puuid string `json:"puuid" gorm:"type:char(36);index:idx_puuid"` UserUuid string `json:"userUuid" gorm:"type:char(36);index:idx_uu"` + Username string `json:"username" gorm:"type:varchar(45) not null"` Dir bool `json:"dir" gorm:"type:tinyint(1) not null;default:0"` Alien bool `json:"alien" gorm:"type:tinyint(1) not null;default:0"` Name string `json:"name" gorm:"type:varchar(255) not null"` @@ -27,3 +28,9 @@ type Matter struct { func (Matter) TableName() string { return TABLE_PREFIX + "matter" } + + +// 获取该Matter的绝对路径。path代表的是相对路径。相对路径的根目录是 CONFIG.MatterPath +func (this *Matter) AbsolutePath() string { + return CONFIG.MatterPath + this.Path +} diff --git a/rest/matter_service.go b/rest/matter_service.go index f873735..224958c 100644 --- a/rest/matter_service.go +++ b/rest/matter_service.go @@ -40,7 +40,7 @@ func (this *MatterService) Init() { } //根据一个文件夹路径,找到最后一个文件夹的uuid,如果中途出错,返回err. -func (this *MatterService) GetDirUuid(userUuid string, dir string) string { +func (this *MatterService) GetDirUuid(user *User, dir string) (puuid string, dirRelativePath string) { if dir == "" { panic(`文件夹不能为空`) @@ -53,7 +53,7 @@ func (this *MatterService) GetDirUuid(userUuid string, dir string) string { } if dir == "/" { - return MATTER_ROOT + return MATTER_ROOT, "" } if dir[len(dir)-1] == '/' { @@ -67,7 +67,8 @@ func (this *MatterService) GetDirUuid(userUuid string, dir string) string { panic("文件夹最多32层。") } - puuid := MATTER_ROOT + puuid = MATTER_ROOT + parentRelativePath := "/" for k, name := range folders { if len(name) > 200 { @@ -78,23 +79,26 @@ func (this *MatterService) GetDirUuid(userUuid string, dir string) string { continue } - matter := this.matterDao.FindByUserUuidAndPuuidAndNameAndDirTrue(userUuid, puuid, name) + matter := this.matterDao.FindByUserUuidAndPuuidAndNameAndDirTrue(user.Uuid, puuid, name) if matter == nil { //创建一个文件夹。这里一般都是通过alien接口来创建的文件夹。 matter = &Matter{ Puuid: puuid, - UserUuid: userUuid, + UserUuid: user.Uuid, + Username: user.Username, Dir: true, Alien: true, Name: name, + Path: parentRelativePath + "/" + name, } matter = this.matterDao.Create(matter) } puuid = matter.Uuid + parentRelativePath = matter.Path } - return puuid + return puuid, parentRelativePath } //获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。 @@ -124,6 +128,26 @@ func (this *MatterService) Upload(file multipart.File, user *User, puuid string, panic("文件名不能超过200") } + //文件夹路径 + var dirAbsolutePath string + var dirRelativePath string + if puuid == "" { + this.PanicBadRequest("puuid必填") + } else { + + if puuid == MATTER_ROOT { + dirAbsolutePath = GetUserFileRootDir(user.Username) + dirRelativePath = "" + } else { + //验证puuid是否存在 + dirMatter := this.matterDao.CheckByUuidAndUserUuid(puuid, user.Uuid) + + dirAbsolutePath = GetUserFileRootDir(user.Username) + dirMatter.Path + dirRelativePath = dirMatter.Path + + } + } + //查找文件夹下面是否有同名文件。 matters := this.matterDao.ListByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, false, filename) //如果有同名的文件,那么我们直接覆盖同名文件。 @@ -132,20 +156,19 @@ func (this *MatterService) Upload(file multipart.File, user *User, puuid string, } //获取文件应该存放在的物理路径的绝对路径和相对路径。 - absolutePath, relativePath := GetUserFileDir(user.Username, false) - absolutePath = absolutePath + "/" + filename - relativePath = relativePath + "/" + filename + fileAbsolutePath := dirAbsolutePath + "/" + filename + fileRelativePath := dirRelativePath + "/" + filename //如果文件已经存在了,那么直接覆盖。 - exist, err := PathExists(absolutePath) + exist, err := PathExists(fileAbsolutePath) this.PanicError(err) if exist { - this.logger.Error("%s已经存在,将其删除", absolutePath) - removeError := os.Remove(absolutePath) + this.logger.Error("%s已经存在,将其删除", fileAbsolutePath) + removeError := os.Remove(fileAbsolutePath) this.PanicError(removeError) } - distFile, err := os.OpenFile(absolutePath, os.O_WRONLY|os.O_CREATE, 0777) + distFile, err := os.OpenFile(fileAbsolutePath, os.O_WRONLY|os.O_CREATE, 0777) this.PanicError(err) defer func() { @@ -163,19 +186,18 @@ func (this *MatterService) Upload(file multipart.File, user *User, puuid string, } } - - //将文件信息存入数据库中。 matter := &Matter{ Puuid: puuid, UserUuid: user.Uuid, + Username: user.Username, Dir: false, Alien: alien, Name: filename, Md5: "", Size: written, Privacy: privacy, - Path: relativePath, + Path: fileRelativePath, } matter = this.matterDao.Create(matter) @@ -216,7 +238,7 @@ func (this *MatterService) httpDownloadFile(filepath string, url string) (int64, } //去指定的url中爬文件 -func (this *MatterService) Crawl(url string, filename string, user *User, puuid string, privacy bool) *Matter { +func (this *MatterService) Crawl(url string, filename string, user *User, puuid string, dirRelativePath string, privacy bool) *Matter { //文件名不能太长。 if len(filename) > 200 { @@ -224,9 +246,8 @@ func (this *MatterService) Crawl(url string, filename string, user *User, puuid } //获取文件应该存放在的物理路径的绝对路径和相对路径。 - absolutePath, relativePath := GetUserFileDir(user.Username, false) - absolutePath = absolutePath + "/" + filename - relativePath = relativePath + "/" + filename + absolutePath := GetUserFileRootDir(user.Username) + dirRelativePath + "/" + filename + relativePath := dirRelativePath + "/" + filename //使用临时文件存放 fmt.Printf("存放于%s", absolutePath) @@ -251,6 +272,7 @@ func (this *MatterService) Crawl(url string, filename string, user *User, puuid matter := &Matter{ Puuid: puuid, UserUuid: user.Uuid, + Username: user.Username, Dir: false, Alien: false, Name: filename, diff --git a/rest/preference_model.go b/rest/preference_model.go index 7fe2b63..26f30d2 100644 --- a/rest/preference_model.go +++ b/rest/preference_model.go @@ -11,6 +11,6 @@ type Preference struct { } // set File's table name to be `profiles` -func (Preference) TableName() string { +func (this *Preference) TableName() string { return TABLE_PREFIX + "preference" } diff --git a/rest/session_model.go b/rest/session_model.go index 5686ad5..a0485f0 100644 --- a/rest/session_model.go +++ b/rest/session_model.go @@ -12,6 +12,6 @@ type Session struct { } // set User's table name to be `profiles` -func (Session) TableName() string { +func (this *Session) TableName() string { return TABLE_PREFIX + "session" } diff --git a/rest/upload_token_model.go b/rest/upload_token_model.go index 2f5a59d..ac999fc 100644 --- a/rest/upload_token_model.go +++ b/rest/upload_token_model.go @@ -16,6 +16,6 @@ type UploadToken struct { Ip string `json:"ip"` } -func (UploadToken) TableName() string { +func (this *UploadToken) TableName() string { return TABLE_PREFIX + "upload_token" } diff --git a/rest/user_model.go b/rest/user_model.go index 92c9598..94a4146 100644 --- a/rest/user_model.go +++ b/rest/user_model.go @@ -43,7 +43,7 @@ type User struct { } // set User's table name to be `profiles` -func (User) TableName() string { +func (this *User) TableName() string { return TABLE_PREFIX + "user" } diff --git a/rest/util_mime.go b/rest/util_mime.go index 8bc3378..8091eb6 100644 --- a/rest/util_mime.go +++ b/rest/util_mime.go @@ -1,6 +1,7 @@ package rest import ( + "os" "path/filepath" "strings" ) @@ -626,6 +627,18 @@ func GetExtension(filename string) string { } +//根据文件名字获取去除后缀的名称 +func GetSimpleFileName(filename string) string { + + for i := len(filename) - 1; i >= 0 && !os.IsPathSeparator(filename[i]); i-- { + if filename[i] == '.' { + return filename[:i] + } + } + return filename + +} + //根据一个后缀名获取MimeType,获取不到默认返回 "application/octet-stream" func GetMimeType(filename string) string { diff --git a/rest/util_path.go b/rest/util_path.go index 5618394..b01934f 100644 --- a/rest/util_path.go +++ b/rest/util_path.go @@ -7,7 +7,6 @@ import ( "os/user" "path/filepath" "strings" - "time" ) //判断文件或文件夹是否已经存在 @@ -150,40 +149,18 @@ func GetLogPath() string { return filePath } -//获取某个用户文件应该存放的位置。这个是相对GetFilePath的路径 -//例如:/zicla/root -func GetUserFileDir(username string, cache bool) (absolutePath string, relativePath string) { +//获取到用户文件的根目录。 +func GetUserFileRootDir(username string) (rootDirPath string) { - filePath := CONFIG.MatterPath + rootDirPath = fmt.Sprintf("%s/%s/%s", CONFIG.MatterPath, username, MATTER_ROOT) - if cache { - //如果是缓存文件夹,那么统一放在cache这个文件夹下面 - firstDir := MATTER_CACHE - - now := time.Now() - datePath := now.Format("2006-01-02") - //毫秒时间戳 - timestamp := now.UnixNano() / 1e6 - - absolutePath = fmt.Sprintf("%s/%s/%s/%s/%d", filePath, username, firstDir, datePath, timestamp) - relativePath = fmt.Sprintf("/%s/%s/%s/%d", username, firstDir, datePath, timestamp) - - } else { - firstDir := MATTER_ROOT - absolutePath = fmt.Sprintf("%s/%s/%s", filePath, username, firstDir) - relativePath = fmt.Sprintf("/%s/%s", username, firstDir) - } - - exists, err := PathExists(absolutePath) - if err != nil { - panic("判断上传文件是否存在时出错!请检查文件夹 " + filePath + " 的访问权限。") - } - if !exists { - err = os.MkdirAll(absolutePath, 0777) - if err != nil { - panic("创建上传文件夹时出错!") - } - } - - return absolutePath, relativePath + return rootDirPath +} + +//获取到用户缓存的根目录。 +func GetUserCacheRootDir(username string) (rootDirPath string) { + + rootDirPath = fmt.Sprintf("%s/%s/%s", CONFIG.MatterPath, username, MATTER_CACHE) + + return rootDirPath }