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  }