diff --git a/rest/alien_controller.go b/rest/alien_controller.go index 8be737b..ebb212e 100644 --- a/rest/alien_controller.go +++ b/rest/alien_controller.go @@ -5,7 +5,6 @@ import ( "net/http" "regexp" "strconv" - "strings" "tank/rest/result" "time" ) @@ -281,7 +280,7 @@ func (this *AlienController) Upload(writer http.ResponseWriter, request *http.Re dirMatter := this.matterDao.CheckWithRootByUuid(uploadToken.FolderUuid, user) - matter := this.matterService.Upload(file, user, dirMatter, uploadToken.Filename, uploadToken.Privacy) + matter := this.matterService.AtomicUpload(file, user, dirMatter, uploadToken.Filename, uploadToken.Privacy) //更新这个uploadToken的信息. uploadToken.ExpireTime = time.Now() @@ -299,6 +298,8 @@ func (this *AlienController) CrawlToken(writer http.ResponseWriter, request *htt } uploadTokenUuid := request.FormValue("uploadTokenUuid") + url := request.FormValue("url") + if uploadTokenUuid == "" { panic("uploadTokenUuid必填") } @@ -314,22 +315,9 @@ func (this *AlienController) CrawlToken(writer http.ResponseWriter, request *htt user := this.userDao.CheckByUuid(uploadToken.UserUuid) - url := request.FormValue("url") - if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) { - panic("资源url必填,并且应该以http://或者https://开头") - } + dirMatter := this.matterDao.CheckWithRootByUuid(uploadToken.FolderUuid, user) - 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) + matter := this.matterService.AtomicCrawl(url, uploadToken.Filename, user, dirMatter, uploadToken.Privacy) //更新这个uploadToken的信息. uploadToken.ExpireTime = time.Now() @@ -347,6 +335,7 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht privacyStr := request.FormValue("privacy") //文件夹路径,以 / 开头。 dir := request.FormValue("dir") + url := request.FormValue("url") if filename == "" { panic("文件名必填") @@ -354,11 +343,6 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht panic(fmt.Sprintf(`【%s】不符合要求,文件名中不能包含以下特殊符号:< > | * ? / \`, filename)) } - url := request.FormValue("url") - if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) { - panic("资源url必填,并且应该以http://或者https://开头") - } - var privacy bool if privacyStr == "" { panic(`文件公有性必填`) @@ -375,7 +359,7 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht user := this.CheckRequestUser(writer, request) dirMatter := this.matterService.CreateDirectories(user, dir) - matter := this.matterService.Crawl(url, filename, user, dirMatter.Uuid, dirMatter.Path, privacy) + matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, privacy) return this.Success(matter) } diff --git a/rest/dav_service.go b/rest/dav_service.go index 0b49fc1..c5cf85b 100644 --- a/rest/dav_service.go +++ b/rest/dav_service.go @@ -230,10 +230,10 @@ func (this *DavService) HandlePut(writer http.ResponseWriter, request *http.Requ //如果存在,那么先删除再说。 srcMatter := this.matterDao.findByUserUuidAndPath(user.Uuid, subPath) if srcMatter != nil { - this.matterService.Delete(srcMatter) + this.matterService.AtomicDelete(srcMatter) } - this.matterService.Upload(request.Body, user, dirMatter, filename, true) + this.matterService.AtomicUpload(request.Body, user, dirMatter, filename, true) } @@ -245,7 +245,7 @@ func (this *DavService) HandleDelete(writer http.ResponseWriter, request *http.R //寻找符合条件的matter. matter := this.matterDao.CheckWithRootByPath(subPath, user) - this.matterService.Delete(matter) + this.matterService.AtomicDelete(matter) } //创建文件夹 @@ -259,7 +259,7 @@ func (this *DavService) HandleMkcol(writer http.ResponseWriter, request *http.Re //寻找符合条件的matter. dirMatter := this.matterDao.CheckWithRootByPath(dirPath, user) - this.matterService.CreateDirectory(dirMatter, thisDirName, user) + this.matterService.AtomicCreateDirectory(dirMatter, thisDirName, user) } @@ -371,9 +371,9 @@ func (this *DavService) HandleMove(writer http.ResponseWriter, request *http.Req //移动到新目录中去。 if destinationDirPath == srcDirPath { //文件夹没变化,相当于重命名。 - this.matterService.Rename(srcMatter, destinationName, user) + this.matterService.AtomicRename(srcMatter, destinationName, user) } else { - this.matterService.Move(srcMatter, destDirMatter, overwrite) + this.matterService.AtomicMove(srcMatter, destDirMatter, overwrite) } this.logger.Info("完成移动 %s => %s", subPath, destDirMatter.Path) @@ -387,7 +387,7 @@ func (this *DavService) HandleCopy(writer http.ResponseWriter, request *http.Req srcMatter, destDirMatter, _, _, destinationName, overwrite := this.prepareMoveCopy(writer, request, user, subPath) //复制到新目录中去。 - this.matterService.Copy(srcMatter, destDirMatter, destinationName,overwrite) + this.matterService.AtomicCopy(srcMatter, destDirMatter, destinationName,overwrite) this.logger.Info("完成复制 %s => %s", subPath, destDirMatter.Path) diff --git a/rest/download/download.go b/rest/download/download.go index 1feab50..c8af574 100644 --- a/rest/download/download.go +++ b/rest/download/download.go @@ -366,33 +366,11 @@ func DownloadFile( // 从指定的url下载一个文件。参考:https://golangcode.com/download-a-file-from-a-url/ -func HttpDownloadFile(filepath string, url string) (int64, error) { - - // Create the file - out, err := os.Create(filepath) - if err != nil { - return 0, err - } - defer func() { - e := out.Close() - PanicError(e) - }() +func HttpDownloadFile(url string) io.Reader { // Get the data resp, err := http.Get(url) - if err != nil { - return 0, err - } - defer func() { - e := resp.Body.Close() - PanicError(e) - }() + PanicError(err) - // Write the body to file - size, err := io.Copy(out, resp.Body) - if err != nil { - return 0, err - } - - return size, nil + return resp.Body } diff --git a/rest/matter_controller.go b/rest/matter_controller.go index 26f2751..a15930a 100644 --- a/rest/matter_controller.go +++ b/rest/matter_controller.go @@ -192,7 +192,7 @@ func (this *MatterController) CreateDirectory(writer http.ResponseWriter, reques dirMatter = this.matterDao.CheckByUuid(puuid) } - matter := this.matterService.CreateDirectory(dirMatter, name, user); + matter := this.matterService.AtomicCreateDirectory(dirMatter, name, user); return this.Success(matter) } @@ -234,7 +234,7 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R dirMatter := this.matterDao.CheckWithRootByUuid(puuid, user) - matter := this.matterService.Upload(file, user, dirMatter, fileName, privacy) + matter := this.matterService.AtomicUpload(file, user, dirMatter, fileName, privacy) return this.Success(matter) } @@ -243,6 +243,10 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Request) *result.WebResult { userUuid := request.FormValue("userUuid") + puuid := request.FormValue("puuid") + url := request.FormValue("url") + privacyStr := request.FormValue("privacy") + user := this.checkUser(writer, request) if user.Role != USER_ROLE_ADMINISTRATOR { userUuid = user.Uuid @@ -254,27 +258,13 @@ 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 { - dirRelativePath = "" - } else { - //找出上一级的文件夹。 - dirMatter := this.matterDao.CheckByUuidAndUserUuid(puuid, userUuid) - dirRelativePath = dirMatter.Path - } - } + dirMatter := this.matterDao.CheckWithRootByUuid(puuid, user) privacy := false - privacyStr := request.FormValue("privacy") if privacyStr == TRUE { privacy = true } - url := request.FormValue("url") if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) { panic("资源url必填,并且应该以http://或者https://开头") } @@ -284,7 +274,7 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re panic("文件名必传") } - matter := this.matterService.Crawl(url, filename, user, puuid, dirRelativePath, privacy) + matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, privacy) return this.Success(matter) } @@ -305,7 +295,7 @@ func (this *MatterController) Delete(writer http.ResponseWriter, request *http.R this.PanicUnauthorized("没有权限") } - this.matterService.Delete(matter) + this.matterService.AtomicDelete(matter) return this.Success("删除成功!") } @@ -336,7 +326,7 @@ func (this *MatterController) DeleteBatch(writer http.ResponseWriter, request *h this.PanicUnauthorized("没有权限") } - this.matterService.Delete(matter) + this.matterService.AtomicDelete(matter) } @@ -358,7 +348,7 @@ func (this *MatterController) Rename(writer http.ResponseWriter, request *http.R this.PanicUnauthorized("没有权限") } - this.matterService.Rename(matter, name, user) + this.matterService.AtomicRename(matter, name, user) return this.Success(matter) } @@ -447,7 +437,7 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req srcMatters = append(srcMatters, srcMatter) } - this.matterService.MoveBatch(srcMatters, destMatter) + this.matterService.AtomicMoveBatch(srcMatters, destMatter) return this.Success(nil) } diff --git a/rest/matter_service.go b/rest/matter_service.go index 62b7a03..b24ce5f 100644 --- a/rest/matter_service.go +++ b/rest/matter_service.go @@ -1,7 +1,6 @@ package rest import ( - "fmt" "io" "net/http" "os" @@ -11,6 +10,10 @@ import ( "tank/rest/result" ) +/** + * 操作文件的Service + * 以 Atomic 开头的方法带有操作锁,这种方法不能被其他的Atomic方法调用,只能提供给外部调用。 + */ //@Service type MatterService struct { Bean @@ -65,7 +68,7 @@ func (this *MatterService) DownloadFile( } //删除文件 -func (this *MatterService) Delete(matter *Matter) { +func (this *MatterService) AtomicDelete(matter *Matter) { if matter == nil { panic(result.BadRequest("matter不能为nil")) @@ -78,18 +81,13 @@ func (this *MatterService) Delete(matter *Matter) { this.matterDao.Delete(matter) } -//开始上传文件 -//上传文件. alien表明文件是否是应用使用的文件。 +//上传文件 func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { if user == nil { panic(result.BadRequest("user cannot be nil.")) } - //操作锁 - this.userService.MatterLock(user.Uuid) - defer this.userService.MatterUnlock(user.Uuid) - //验证dirMatter if dirMatter == nil { panic(result.BadRequest("dirMatter cannot be nil.")) @@ -166,6 +164,20 @@ func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, return matter } +//上传文件 +func (this *MatterService) AtomicUpload(file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { + + if user == nil { + panic(result.BadRequest("user cannot be nil.")) + } + + //操作锁 + this.userService.MatterLock(user.Uuid) + defer this.userService.MatterUnlock(user.Uuid) + + return this.Upload(file, user, dirMatter, filename, privacy) +} + //内部创建文件,不带操作锁。 func (this *MatterService) innerCreateDirectory(dirMatter *Matter, name string, user *User) *Matter { @@ -241,7 +253,7 @@ func (this *MatterService) innerCreateDirectory(dirMatter *Matter, name string, } //在dirMatter中创建文件夹 返回刚刚创建的这个文件夹 -func (this *MatterService) CreateDirectory(dirMatter *Matter, name string, user *User) *Matter { +func (this *MatterService) AtomicCreateDirectory(dirMatter *Matter, name string, user *User) *Matter { //操作锁 this.userService.MatterLock(user.Uuid) @@ -325,7 +337,7 @@ func (this *MatterService) innerMove(srcMatter *Matter, destDirMatter *Matter) { } //将一个srcMatter放置到另一个destMatter(必须为文件夹)下 -func (this *MatterService) Move(srcMatter *Matter, destDirMatter *Matter, overwrite bool) { +func (this *MatterService) AtomicMove(srcMatter *Matter, destDirMatter *Matter, overwrite bool) { if srcMatter == nil { panic(result.BadRequest("srcMatter cannot be nil.")) @@ -358,7 +370,7 @@ func (this *MatterService) Move(srcMatter *Matter, destDirMatter *Matter, overwr } //将一个srcMatter放置到另一个destMatter(必须为文件夹)下 -func (this *MatterService) MoveBatch(srcMatters []*Matter, destDirMatter *Matter) { +func (this *MatterService) AtomicMoveBatch(srcMatters []*Matter, destDirMatter *Matter) { if destDirMatter == nil { panic(result.BadRequest("destDirMatter cannot be nil.")) @@ -450,7 +462,7 @@ func (this *MatterService) innerCopy(srcMatter *Matter, destDirMatter *Matter, n } //将一个srcMatter复制到另一个destMatter(必须为文件夹)下,名字叫做name -func (this *MatterService) Copy(srcMatter *Matter, destDirMatter *Matter, name string, overwrite bool) { +func (this *MatterService) AtomicCopy(srcMatter *Matter, destDirMatter *Matter, name string, overwrite bool) { if srcMatter == nil { panic(result.BadRequest("srcMatter cannot be nil.")) @@ -471,7 +483,7 @@ func (this *MatterService) Copy(srcMatter *Matter, destDirMatter *Matter, name s } //将一个matter 重命名为 name -func (this *MatterService) Rename(matter *Matter, name string, user *User) { +func (this *MatterService) AtomicRename(matter *Matter, name string, user *User) { if user == nil { this.PanicBadRequest("user cannot be nil") @@ -623,52 +635,25 @@ func (this *MatterService) Detail(uuid string) *Matter { } //去指定的url中爬文件 -func (this *MatterService) Crawl(url string, filename string, user *User, puuid string, dirRelativePath string, privacy bool) *Matter { +func (this *MatterService) AtomicCrawl(url string, filename string, user *User, dirMatter *Matter, privacy bool) *Matter { - //文件名不能太长。 - if len(filename) > 200 { - panic("文件名不能超过200") + if user == nil { + panic(result.BadRequest("user cannot be nil.")) } - //获取文件应该存放在的物理路径的绝对路径和相对路径。 - absolutePath := GetUserFileRootDir(user.Username) + dirRelativePath + "/" + filename - relativePath := dirRelativePath + "/" + filename + if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) { + panic("资源url必填,并且应该以http://或者https://开头") + } - //使用临时文件存放 - fmt.Printf("存放于%s", absolutePath) - size, err := download.HttpDownloadFile(absolutePath, url) + //操作锁 + this.userService.MatterLock(user.Uuid) + defer this.userService.MatterUnlock(user.Uuid) + + //从指定的url下载一个文件。参考:https://golangcode.com/download-a-file-from-a-url/ + resp, err := http.Get(url) this.PanicError(err) - //判断用户自身上传大小的限制。 - if user.SizeLimit >= 0 { - if size > user.SizeLimit { - panic("您最大只能上传" + HumanFileSize(user.SizeLimit) + "的文件") - } - } - - //查找文件夹下面是否有同名文件。 - matters := this.matterDao.ListByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, false, filename) - //如果有同名的文件,那么我们直接覆盖同名文件。 - for _, dbFile := range matters { - this.Delete(dbFile) - } - - //将文件信息存入数据库中。 - matter := &Matter{ - Puuid: puuid, - UserUuid: user.Uuid, - Username: user.Username, - Dir: false, - Name: filename, - Md5: "", - Size: size, - Privacy: privacy, - Path: relativePath, - } - - matter = this.matterDao.Create(matter) - - return matter + return this.Upload(resp.Body, user, dirMatter, filename, privacy) } //调整一个Matter的path值