github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/service/admin/file.go (about) 1 package admin 2 3 import ( 4 "context" 5 "strings" 6 7 model "github.com/cloudreve/Cloudreve/v3/models" 8 "github.com/cloudreve/Cloudreve/v3/pkg/filesystem" 9 "github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx" 10 "github.com/cloudreve/Cloudreve/v3/pkg/serializer" 11 "github.com/cloudreve/Cloudreve/v3/service/explorer" 12 "github.com/gin-gonic/gin" 13 ) 14 15 // FileService 文件ID服务 16 type FileService struct { 17 ID uint `uri:"id" json:"id" binding:"required"` 18 } 19 20 // FileBatchService 文件批量操作服务 21 type FileBatchService struct { 22 ID []uint `json:"id" binding:"min=1"` 23 Force bool `json:"force"` 24 UnlinkOnly bool `json:"unlink"` 25 } 26 27 // ListFolderService 列目录结构 28 type ListFolderService struct { 29 Path string `uri:"path" binding:"required,max=65535"` 30 ID uint `uri:"id" binding:"required"` 31 Type string `uri:"type" binding:"eq=policy|eq=user"` 32 } 33 34 // List 列出指定路径下的目录 35 func (service *ListFolderService) List(c *gin.Context) serializer.Response { 36 if service.Type == "policy" { 37 // 列取存储策略中的目录 38 policy, err := model.GetPolicyByID(service.ID) 39 if err != nil { 40 return serializer.Err(serializer.CodePolicyNotExist, "", err) 41 } 42 43 // 创建文件系统 44 fs, err := filesystem.NewAnonymousFileSystem() 45 if err != nil { 46 return serializer.Err(serializer.CodeCreateFSError, "", err) 47 } 48 defer fs.Recycle() 49 50 // 列取存储策略中的文件 51 fs.Policy = &policy 52 res, err := fs.ListPhysical(c.Request.Context(), service.Path) 53 if err != nil { 54 return serializer.Err(serializer.CodeListFilesError, "", err) 55 } 56 57 return serializer.Response{ 58 Data: serializer.BuildObjectList(0, res, nil), 59 } 60 61 } 62 63 // 列取用户空间目录 64 // 查找用户 65 user, err := model.GetUserByID(service.ID) 66 if err != nil { 67 return serializer.Err(serializer.CodeUserNotFound, "", err) 68 } 69 70 // 创建文件系统 71 fs, err := filesystem.NewFileSystem(&user) 72 if err != nil { 73 return serializer.Err(serializer.CodeCreateFSError, "", err) 74 } 75 defer fs.Recycle() 76 77 // 列取目录 78 res, err := fs.List(c.Request.Context(), service.Path, nil) 79 if err != nil { 80 return serializer.Err(serializer.CodeListFilesError, "", err) 81 } 82 83 return serializer.Response{ 84 Data: serializer.BuildObjectList(0, res, nil), 85 } 86 } 87 88 // Delete 删除文件 89 func (service *FileBatchService) Delete(c *gin.Context) serializer.Response { 90 files, err := model.GetFilesByIDs(service.ID, 0) 91 if err != nil { 92 return serializer.DBErr("Failed to list files for deleting", err) 93 } 94 95 // 根据用户分组 96 userFile := make(map[uint][]model.File) 97 for i := 0; i < len(files); i++ { 98 if _, ok := userFile[files[i].UserID]; !ok { 99 userFile[files[i].UserID] = []model.File{} 100 } 101 userFile[files[i].UserID] = append(userFile[files[i].UserID], files[i]) 102 } 103 104 // 异步执行删除 105 go func(files map[uint][]model.File) { 106 for uid, file := range files { 107 var ( 108 fs *filesystem.FileSystem 109 err error 110 ) 111 user, err := model.GetUserByID(uid) 112 if err != nil { 113 fs, err = filesystem.NewAnonymousFileSystem() 114 if err != nil { 115 continue 116 } 117 } else { 118 fs, err = filesystem.NewFileSystem(&user) 119 if err != nil { 120 fs.Recycle() 121 continue 122 } 123 } 124 125 // 汇总文件ID 126 ids := make([]uint, 0, len(file)) 127 for i := 0; i < len(file); i++ { 128 ids = append(ids, file[i].ID) 129 } 130 131 // 执行删除 132 fs.Delete(context.Background(), []uint{}, ids, service.Force, service.UnlinkOnly) 133 fs.Recycle() 134 } 135 }(userFile) 136 137 // 分组执行删除 138 return serializer.Response{} 139 140 } 141 142 // Get 预览文件 143 func (service *FileService) Get(c *gin.Context) serializer.Response { 144 file, err := model.GetFilesByIDs([]uint{service.ID}, 0) 145 if err != nil { 146 return serializer.Err(serializer.CodeFileNotFound, "", err) 147 } 148 149 ctx := context.WithValue(context.Background(), fsctx.FileModelCtx, &file[0]) 150 var subService explorer.FileIDService 151 res := subService.PreviewContent(ctx, c, false) 152 153 return res 154 } 155 156 // Files 列出文件 157 func (service *AdminListService) Files() serializer.Response { 158 var res []model.File 159 total := 0 160 161 tx := model.DB.Model(&model.File{}) 162 if service.OrderBy != "" { 163 tx = tx.Order(service.OrderBy) 164 } 165 166 for k, v := range service.Conditions { 167 tx = tx.Where(k+" = ?", v) 168 } 169 170 if len(service.Searches) > 0 { 171 search := "" 172 for k, v := range service.Searches { 173 search += k + " like '%" + v + "%' OR " 174 } 175 search = strings.TrimSuffix(search, " OR ") 176 tx = tx.Where(search) 177 } 178 179 // 计算总数用于分页 180 tx.Count(&total) 181 182 // 查询记录 183 tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res) 184 185 // 查询对应用户 186 users := make(map[uint]model.User) 187 for _, file := range res { 188 users[file.UserID] = model.User{} 189 } 190 191 userIDs := make([]uint, 0, len(users)) 192 for k := range users { 193 userIDs = append(userIDs, k) 194 } 195 196 var userList []model.User 197 model.DB.Where("id in (?)", userIDs).Find(&userList) 198 199 for _, v := range userList { 200 users[v.ID] = v 201 } 202 203 return serializer.Response{Data: map[string]interface{}{ 204 "total": total, 205 "items": res, 206 "users": users, 207 }} 208 }