From f2bed9ac334892d0bd258191c2bb8e18237d917e Mon Sep 17 00:00:00 2001 From: zicla Date: Wed, 24 Apr 2019 22:43:58 +0800 Subject: [PATCH] Finish some code refine work. --- rest/alien_controller.go | 4 +- rest/dav_service.go | 3 +- rest/matter_controller.go | 8 +- rest/matter_dao.go | 30 +++- rest/matter_model.go | 3 +- rest/matter_service.go | 322 ++++++++++++++++++-------------------- 6 files changed, 189 insertions(+), 181 deletions(-) diff --git a/rest/alien_controller.go b/rest/alien_controller.go index 58c81a9..ad76124 100644 --- a/rest/alien_controller.go +++ b/rest/alien_controller.go @@ -279,7 +279,9 @@ func (this *AlienController) Upload(writer http.ResponseWriter, request *http.Re panic("文件大小不正确") } - matter := this.matterService.Upload(file, user, uploadToken.FolderUuid, uploadToken.Filename, uploadToken.Privacy, true) + dirMatter := this.matterDao.CheckDirByUuid(uploadToken.FolderUuid, user) + + matter := this.matterService.Upload(file, user, dirMatter, uploadToken.Filename, uploadToken.Privacy) //更新这个uploadToken的信息. uploadToken.ExpireTime = time.Now() diff --git a/rest/dav_service.go b/rest/dav_service.go index cf4317a..b6aec2f 100644 --- a/rest/dav_service.go +++ b/rest/dav_service.go @@ -252,7 +252,8 @@ func (this *DavService) HandlePut(writer http.ResponseWriter, request *http.Requ this.matterService.Delete(srcMatter) } - this.matterService.Upload(request.Body, user, matter.Uuid, filename, true, false) + + this.matterService.Upload(request.Body, user, matter, filename, true) } diff --git a/rest/matter_controller.go b/rest/matter_controller.go index 9f1313e..261cece 100644 --- a/rest/matter_controller.go +++ b/rest/matter_controller.go @@ -170,7 +170,6 @@ func (this *MatterController) Page(writer http.ResponseWriter, request *http.Req return this.Success(pager) } - //创建一个文件夹。 func (this *MatterController) CreateDirectory(writer http.ResponseWriter, request *http.Request) *result.WebResult { @@ -178,7 +177,6 @@ func (this *MatterController) CreateDirectory(writer http.ResponseWriter, reques name := request.FormValue("name") userUuid := request.FormValue("userUuid") - //管理员可以指定给某个用户创建文件夹。 user := this.checkUser(writer, request) if user.Role != USER_ROLE_ADMINISTRATOR { @@ -198,8 +196,6 @@ func (this *MatterController) CreateDirectory(writer http.ResponseWriter, reques return this.Success(matter) } - - //上传文件 func (this *MatterController) Upload(writer http.ResponseWriter, request *http.Request) *result.WebResult { @@ -236,7 +232,9 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R fileName = fileName[pos+1:] } - matter := this.matterService.Upload(file, user, puuid, fileName, privacy, false) + dirMatter := this.matterDao.CheckDirByUuid(puuid, user) + + matter := this.matterService.Upload(file, user, dirMatter, fileName, privacy) return this.Success(matter) } diff --git a/rest/matter_dao.go b/rest/matter_dao.go index c881cb5..b46fba7 100644 --- a/rest/matter_dao.go +++ b/rest/matter_dao.go @@ -31,21 +31,39 @@ func (this *MatterDao) FindByUuid(uuid string) *Matter { var matter Matter db := CONTEXT.DB.Where(&Matter{Base: Base{Uuid: uuid}}).First(&matter) if db.Error != nil { - return nil + if db.Error.Error() == result.DB_ERROR_NOT_FOUND { + return nil + } else { + this.PanicError(db.Error) + } } return &matter } //按照Id查询文件 func (this *MatterDao) CheckByUuid(uuid string) *Matter { + matter := this.FindByUuid(uuid) + if matter == nil { + this.PanicNotFound("%s 对应的matter不存在", uuid) + } + return matter +} - // Read - var matter Matter - db := CONTEXT.DB.Where(&Matter{Base: Base{Uuid: uuid}}).First(&matter) - this.PanicError(db.Error) - return &matter +//按照uuid查找一个文件夹,可能返回root对应的matter. +func (this *MatterDao) CheckDirByUuid(uuid string, user *User) *Matter { + var matter *Matter + if uuid == MATTER_ROOT { + if user == nil { + this.PanicBadRequest("user cannot be nil.") + } + matter = NewRootMatter(user) + } else { + matter = this.CheckByUuid(uuid) + } + + return matter } //按照名字查询文件夹 diff --git a/rest/matter_model.go b/rest/matter_model.go index c27e499..be0749d 100644 --- a/rest/matter_model.go +++ b/rest/matter_model.go @@ -15,7 +15,7 @@ const ( ) /** - * 文件。alien表示是否是应用内使用的文件,比如说蓝眼云盘的头像,alien = true 这种文件在上传时不需要指定存放目录,会统一放在同一个文件夹下。 + * 文件。 */ type Matter struct { Base @@ -23,7 +23,6 @@ type Matter struct { 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"` Md5 string `json:"md5" gorm:"type:varchar(45)"` Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"` diff --git a/rest/matter_service.go b/rest/matter_service.go index ce3b550..83035a8 100644 --- a/rest/matter_service.go +++ b/rest/matter_service.go @@ -71,53 +71,43 @@ func (this *MatterService) Delete(matter *Matter) { panic(result.BadRequest("matter不能为nil")) } - - //操作锁 this.userService.MatterLock(matter.UserUuid) defer this.userService.MatterUnlock(matter.UserUuid) - - this.matterDao.Delete(matter) - } - //开始上传文件 //上传文件. alien表明文件是否是应用使用的文件。 -func (this *MatterService) Upload(file io.Reader, user *User, puuid string, filename string, privacy bool, alien bool) *Matter { +func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { - //文件名不能太长。 - if len(filename) > 200 { - panic("文件名不能超过200") + if user == nil { + panic(result.BadRequest("user cannot be nil.")) } - //文件夹路径 - var dirAbsolutePath string - var dirRelativePath string - if puuid == "" { - this.PanicBadRequest("puuid必填") - } else { + //操作锁 + this.userService.MatterLock(user.Uuid) + defer this.userService.MatterUnlock(user.Uuid) - 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 + //验证dirMatter + if dirMatter == nil { + panic(result.BadRequest("dirMatter cannot be nil.")) + } - } + //文件名不能太长。 + if len(filename) > MATTER_NAME_MAX_LENGTH { + panic(result.BadRequest("文件名不能超过%s", MATTER_NAME_MAX_LENGTH)) } - //查找文件夹下面是否有同名文件。 - matters := this.matterDao.ListByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, false, filename) - //如果有同名的文件,那么我们直接覆盖同名文件。 - for _, dbFile := range matters { - this.PanicBadRequest("该目录下%s已经存在了", dbFile.Name) + //文件夹路径 + dirAbsolutePath := dirMatter.AbsolutePath() + dirRelativePath := dirMatter.Path + + count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, false, filename) + if count > 0 { + panic(result.BadRequest("该目录下%s已经存在了", filename)) } //获取文件应该存放在的物理路径的绝对路径和相对路径。 @@ -136,112 +126,51 @@ func (this *MatterService) Upload(file io.Reader, user *User, puuid string, file this.PanicError(removeError) } - distFile, err := os.OpenFile(fileAbsolutePath, os.O_WRONLY|os.O_CREATE, 0777) + destFile, err := os.OpenFile(fileAbsolutePath, os.O_WRONLY|os.O_CREATE, 0777) this.PanicError(err) defer func() { - err := distFile.Close() + err := destFile.Close() this.PanicError(err) }() - written, err := io.Copy(distFile, file) + fileSize, err := io.Copy(destFile, file) this.PanicError(err) - this.logger.Info("上传文件%s大小为%v", filename, HumanFileSize(written)) + this.logger.Info("上传文件 %s 大小为 %v ", filename, HumanFileSize(fileSize)) //判断用户自身上传大小的限制。 if user.SizeLimit >= 0 { - if written > user.SizeLimit { - this.PanicBadRequest("文件大小超出限制 " + HumanFileSize(user.SizeLimit) + ">" + HumanFileSize(written)) + if fileSize > user.SizeLimit { + //删除上传过来的内容 + err = os.Remove(fileAbsolutePath) + this.PanicError(err) + + panic(result.BadRequest("文件大小超出限制 %s > %s ", HumanFileSize(user.SizeLimit), HumanFileSize(fileSize))) } } //将文件信息存入数据库中。 matter := &Matter{ - Puuid: puuid, + Puuid: dirMatter.Uuid, UserUuid: user.Uuid, Username: user.Username, Dir: false, - Alien: alien, Name: filename, Md5: "", - Size: written, + Size: fileSize, Privacy: privacy, Path: fileRelativePath, } - matter = this.matterDao.Create(matter) return matter } - - -//根据一个文件夹路径,找到最后一个文件夹的uuid,如果中途出错,返回err. -func (this *MatterService) GetDirUuid(user *User, dir string) (puuid string, dirRelativePath 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 MATTER_ROOT, "" - } - - if dir[len(dir)-1] == '/' { - dir = dir[:len(dir)-1] - } - - //递归找寻文件的上级目录uuid. - folders := strings.Split(dir, "/") - - if len(folders) > 32 { - panic("文件夹最多32层。") - } - - puuid = MATTER_ROOT - parentRelativePath := "/" - for k, name := range folders { - - if len(name) > 200 { - panic("每级文件夹的最大长度为200") - } - - if k == 0 { - continue - } - - matter := this.matterDao.FindByUserUuidAndPuuidAndNameAndDirTrue(user.Uuid, puuid, name) - if matter == nil { - //创建一个文件夹。这里一般都是通过alien接口来创建的文件夹。 - matter = &Matter{ - Puuid: puuid, - 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, parentRelativePath -} - //在dirMatter中创建文件夹 返回刚刚创建的这个文件夹 func (this *MatterService) CreateDirectory(dirMatter *Matter, name string, user *User) *Matter { + //操作锁 this.userService.MatterLock(user.Uuid) defer this.userService.MatterUnlock(user.Uuid) @@ -273,7 +202,6 @@ func (this *MatterService) CreateDirectory(dirMatter *Matter, name string, user } if m, _ := regexp.MatchString(`[<>|*?/\\]`, name); m { - panic(result.BadRequest(`名称中不能包含以下特殊符号:< > | * ? / \`)) } @@ -317,6 +245,129 @@ func (this *MatterService) CreateDirectory(dirMatter *Matter, name string, user return matter } + +//将一个srcMatter复制到另一个destMatter(必须为文件夹)下,名字叫做name +func (this *MatterService) Copy(srcMatter *Matter, destDirMatter *Matter, name string) { + + if !destDirMatter.Dir { + this.PanicBadRequest("目标必须为文件夹") + } + + if srcMatter.Dir { + + //如果源是文件夹 + + //在目标地址创建新文件夹。 + newMatter := &Matter{ + Puuid: destDirMatter.Uuid, + UserUuid: srcMatter.UserUuid, + Username: srcMatter.Username, + Dir: srcMatter.Dir, + Name: name, + Md5: "", + Size: srcMatter.Size, + Privacy: srcMatter.Privacy, + Path: destDirMatter.Path + "/" + name, + } + + newMatter = this.matterDao.Create(newMatter) + + //复制子文件或文件夹 + matters := this.matterDao.List(srcMatter.Uuid, srcMatter.UserUuid, nil) + for _, m := range matters { + this.Copy(m, newMatter, m.Name) + } + + } else { + //如果源是普通文件 + destAbsolutePath := destDirMatter.AbsolutePath() + "/" + name + srcAbsolutePath := srcMatter.AbsolutePath() + + //物理文件进行复制 + CopyFile(srcAbsolutePath, destAbsolutePath) + + //创建新文件的数据库信息。 + newMatter := &Matter{ + Puuid: destDirMatter.Uuid, + UserUuid: srcMatter.UserUuid, + Username: srcMatter.Username, + Dir: srcMatter.Dir, + Name: name, + Md5: "", + Size: srcMatter.Size, + Privacy: srcMatter.Privacy, + Path: destDirMatter.Path + "/" + name, + } + + newMatter = this.matterDao.Create(newMatter) + + } + +} + + +//根据一个文件夹路径,找到最后一个文件夹的uuid,如果中途出错,返回err. +func (this *MatterService) GetDirUuid(user *User, dir string) (puuid string, dirRelativePath 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 MATTER_ROOT, "" + } + + if dir[len(dir)-1] == '/' { + dir = dir[:len(dir)-1] + } + + //递归找寻文件的上级目录uuid. + folders := strings.Split(dir, "/") + + if len(folders) > 32 { + panic("文件夹最多32层。") + } + + puuid = MATTER_ROOT + parentRelativePath := "/" + for k, name := range folders { + + if len(name) > 200 { + panic("每级文件夹的最大长度为200") + } + + if k == 0 { + continue + } + + matter := this.matterDao.FindByUserUuidAndPuuidAndNameAndDirTrue(user.Uuid, puuid, name) + if matter == nil { + //创建一个文件夹。这里一般都是通过alien接口来创建的文件夹。 + matter = &Matter{ + Puuid: puuid, + UserUuid: user.Uuid, + Username: user.Username, + Dir: true, + Name: name, + Path: parentRelativePath + "/" + name, + } + matter = this.matterDao.Create(matter) + } + + puuid = matter.Uuid + parentRelativePath = matter.Path + } + + return puuid, parentRelativePath +} + + //获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。 func (this *MatterService) Detail(uuid string) *Matter { @@ -404,7 +455,6 @@ func (this *MatterService) Crawl(url string, filename string, user *User, puuid UserUuid: user.Uuid, Username: user.Username, Dir: false, - Alien: false, Name: filename, Md5: "", Size: size, @@ -496,66 +546,6 @@ func (this *MatterService) Move(srcMatter *Matter, destMatter *Matter) { return } -//将一个srcMatter复制到另一个destMatter(必须为文件夹)下,名字叫做name -func (this *MatterService) Copy(srcMatter *Matter, destDirMatter *Matter, name string) { - - if !destDirMatter.Dir { - this.PanicBadRequest("目标必须为文件夹") - } - - if srcMatter.Dir { - - //如果源是文件夹 - - //在目标地址创建新文件夹。 - newMatter := &Matter{ - Puuid: destDirMatter.Uuid, - UserUuid: srcMatter.UserUuid, - Username: srcMatter.Username, - Dir: srcMatter.Dir, - Alien: srcMatter.Alien, - Name: name, - Md5: "", - Size: srcMatter.Size, - Privacy: srcMatter.Privacy, - Path: destDirMatter.Path + "/" + name, - } - - newMatter = this.matterDao.Create(newMatter) - - //复制子文件或文件夹 - matters := this.matterDao.List(srcMatter.Uuid, srcMatter.UserUuid, nil) - for _, m := range matters { - this.Copy(m, newMatter, m.Name) - } - - } else { - //如果源是普通文件 - destAbsolutePath := destDirMatter.AbsolutePath() + "/" + name - srcAbsolutePath := srcMatter.AbsolutePath() - - //物理文件进行复制 - CopyFile(srcAbsolutePath, destAbsolutePath) - - //创建新文件的数据库信息。 - newMatter := &Matter{ - Puuid: destDirMatter.Uuid, - UserUuid: srcMatter.UserUuid, - Username: srcMatter.Username, - Dir: srcMatter.Dir, - Alien: srcMatter.Alien, - Name: name, - Md5: "", - Size: srcMatter.Size, - Privacy: srcMatter.Privacy, - Path: destDirMatter.Path + "/" + name, - } - - newMatter = this.matterDao.Create(newMatter) - - } - -} //将一个matter 重命名为 name func (this *MatterService) Rename(matter *Matter, name string, user *User) {