package rest import ( "io" "mime/multipart" "os" "regexp" "strings" ) //@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 }