diff --git a/rest/matter_controller.go b/rest/matter_controller.go index ea756aa..36ed011 100644 --- a/rest/matter_controller.go +++ b/rest/matter_controller.go @@ -46,6 +46,7 @@ func (this *MatterController) RegisterRoutes() map[string]func(writer http.Respo //每个Controller需要主动注册自己的路由。 routeMap["/api/matter/create/directory"] = this.Wrap(this.CreateDirectory, USER_ROLE_USER) routeMap["/api/matter/upload"] = this.Wrap(this.Upload, USER_ROLE_USER) + routeMap["/api/matter/crawl"] = this.Wrap(this.Crawl, USER_ROLE_USER) routeMap["/api/matter/delete"] = this.Wrap(this.Delete, USER_ROLE_USER) routeMap["/api/matter/delete/batch"] = this.Wrap(this.DeleteBatch, USER_ROLE_USER) routeMap["/api/matter/rename"] = this.Wrap(this.Rename, USER_ROLE_USER) @@ -265,6 +266,47 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R return this.Success(matter) } +//从一个Url中去爬取资源 +func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Request) *WebResult { + + userUuid := request.FormValue("userUuid") + user := this.checkUser(writer, request) + if user.Role != USER_ROLE_ADMINISTRATOR { + userUuid = user.Uuid + } + user = this.userDao.CheckByUuid(userUuid) + + puuid := request.FormValue("puuid") + if puuid == "" { + return this.Error("puuid必填") + } else { + if puuid != "root" { + //找出上一级的文件夹。 + this.matterDao.CheckByUuidAndUserUuid(puuid, userUuid) + } + } + + 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://开头") + } + + filename := request.FormValue("filename") + if filename == "" { + panic("文件名必传") + } + + matter := this.matterService.Crawl(url, filename, user, puuid, privacy) + + return this.Success(matter) +} + //删除一个文件 func (this *MatterController) Delete(writer http.ResponseWriter, request *http.Request) *WebResult { @@ -331,7 +373,6 @@ func (this *MatterController) Rename(writer http.ResponseWriter, request *http.R panic("name长度不能超过200") } - //找出该文件或者文件夹 matter := this.matterDao.CheckByUuid(uuid) diff --git a/rest/matter_model.go b/rest/matter_model.go index 27d5d1d..f6aeea8 100644 --- a/rest/matter_model.go +++ b/rest/matter_model.go @@ -1,5 +1,9 @@ package rest + +/** + * 文件。alien表示是否是应用内使用的文件,比如说蓝眼云盘的头像,alien = true 这种文件在上传时不需要指定存放目录,会统一放在同一个文件夹下。 + */ type Matter struct { Base Puuid string `json:"puuid"` diff --git a/rest/matter_service.go b/rest/matter_service.go index 0068d3b..5f8f4b8 100644 --- a/rest/matter_service.go +++ b/rest/matter_service.go @@ -166,6 +166,86 @@ func (this *MatterService) Upload(file multipart.File, user *User, puuid string, return matter } +// 从指定的url下载一个文件。参考:https://golangcode.com/download-a-file-from-a-url/ +func (this *MatterService) httpDownloadFile(filepath string, url string) (int64, error) { + + // Create the file + out, err := os.Create(filepath) + if err != nil { + return 0, err + } + defer out.Close() + + // Get the data + resp, err := http.Get(url) + if err != nil { + return 0, err + } + defer resp.Body.Close() + + // Write the body to file + size, err := io.Copy(out, resp.Body) + if err != nil { + return 0, err + } + + return size, nil +} + +//去指定的url中爬文件 +func (this *MatterService) Crawl(url string, filename string, user *User, puuid string, privacy bool) *Matter { + + //文件名不能太长。 + if len(filename) > 200 { + panic("文件名不能超过200") + } + + //获取文件应该存放在的物理路径的绝对路径和相对路径。 + absolutePath, relativePath := GetUserFilePath(user.Username) + absolutePath = absolutePath + "/" + filename + relativePath = relativePath + "/" + filename + + //使用临时文件存放 + fmt.Printf("存放于%s", absolutePath) + size, err := this.httpDownloadFile(absolutePath+".tmp", url) + this.PanicError(err) + + //完成了之后重命名 + err = os.Rename(absolutePath+".tmp", absolutePath) + this.PanicError(err) + + //TODO:判断用户自身上传大小的限制。 + 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.matterDao.Delete(dbFile) + } + + //将文件信息存入数据库中。 + matter := &Matter{ + Puuid: puuid, + UserUuid: user.Uuid, + Dir: false, + Alien: false, + Name: filename, + Md5: "", + Size: size, + Privacy: privacy, + Path: relativePath, + } + + matter = this.matterDao.Create(matter) + + return matter +} + //图片预处理功能。 func (this *MatterService) ResizeImage(writer http.ResponseWriter, request *http.Request, matter *Matter) { @@ -293,9 +373,6 @@ func (w *countingWriter) Write(p []byte) (n int, err error) { return len(p), nil } - - - //检查Last-Modified头。返回true: 请求已经完成了。(言下之意,文件没有修改过) 返回false:文件修改过。 func (this *MatterService) checkLastModified(w http.ResponseWriter, r *http.Request, modifyTime time.Time) bool { if modifyTime.IsZero() { @@ -377,7 +454,6 @@ func (this *MatterService) checkETag(w http.ResponseWriter, r *http.Request, mod return rangeReq, false } - // parseRange parses a Range header string as per RFC 2616. func (this *MatterService) parseRange(s string, size int64) ([]httpRange, error) { if s == "" { @@ -436,7 +512,6 @@ func (this *MatterService) parseRange(s string, size int64) ([]httpRange, error) return ranges, nil } - // rangesMIMESize returns the number of bytes it takes to encode the // provided ranges as a multipart response. func (this *MatterService) rangesMIMESize(ranges []httpRange, contentType string, contentSize int64) (encSize int64) {