您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

file_service.py 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #
  2. # Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. from flask_login import current_user
  17. from peewee import fn
  18. from api.db import FileType
  19. from api.db.db_models import DB, File2Document, Knowledgebase
  20. from api.db.db_models import File, Document
  21. from api.db.services.common_service import CommonService
  22. from api.utils import get_uuid
  23. from rag.utils import MINIO
  24. class FileService(CommonService):
  25. model = File
  26. @classmethod
  27. @DB.connection_context()
  28. def get_by_pf_id(cls, tenant_id, pf_id, page_number, items_per_page,
  29. orderby, desc, keywords):
  30. if keywords:
  31. files = cls.model.select().where(
  32. (cls.model.tenant_id == tenant_id)
  33. & (cls.model.parent_id == pf_id), (fn.LOWER(cls.model.name).like(f"%%{keywords.lower()}%%")))
  34. else:
  35. files = cls.model.select().where((cls.model.tenant_id == tenant_id)
  36. & (cls.model.parent_id == pf_id))
  37. count = files.count()
  38. if desc:
  39. files = files.order_by(cls.model.getter_by(orderby).desc())
  40. else:
  41. files = files.order_by(cls.model.getter_by(orderby).asc())
  42. files = files.paginate(page_number, items_per_page)
  43. res_files = list(files.dicts())
  44. for file in res_files:
  45. if file["type"] == FileType.FOLDER.value:
  46. file["size"] = cls.get_folder_size(file["id"])
  47. file['kbs_info'] = []
  48. continue
  49. kbs_info = cls.get_kb_id_by_file_id(file['id'])
  50. file['kbs_info'] = kbs_info
  51. return res_files, count
  52. @classmethod
  53. @DB.connection_context()
  54. def get_kb_id_by_file_id(cls, file_id):
  55. kbs = (cls.model.select(*[Knowledgebase.id, Knowledgebase.name])
  56. .join(File2Document, on=(File2Document.file_id == file_id))
  57. .join(Document, on=(File2Document.document_id == Document.id))
  58. .join(Knowledgebase, on=(Knowledgebase.id == Document.kb_id))
  59. .where(cls.model.id == file_id))
  60. if not kbs: return []
  61. kbs_info_list = []
  62. for kb in list(kbs.dicts()):
  63. kbs_info_list.append({"kb_id": kb['id'], "kb_name": kb['name']})
  64. return kbs_info_list
  65. @classmethod
  66. @DB.connection_context()
  67. def get_by_pf_id_name(cls, id, name):
  68. file = cls.model.select().where((cls.model.parent_id == id) & (cls.model.name == name))
  69. if file.count():
  70. e, file = cls.get_by_id(file[0].id)
  71. if not e:
  72. raise RuntimeError("Database error (File retrieval)!")
  73. return file
  74. return None
  75. @classmethod
  76. @DB.connection_context()
  77. def get_id_list_by_id(cls, id, name, count, res):
  78. if count < len(name):
  79. file = cls.get_by_pf_id_name(id, name[count])
  80. if file:
  81. res.append(file.id)
  82. return cls.get_id_list_by_id(file.id, name, count + 1, res)
  83. else:
  84. return res
  85. else:
  86. return res
  87. @classmethod
  88. @DB.connection_context()
  89. def get_all_innermost_file_ids(cls, folder_id, result_ids):
  90. subfolders = cls.model.select().where(cls.model.parent_id == folder_id)
  91. if subfolders.exists():
  92. for subfolder in subfolders:
  93. cls.get_all_innermost_file_ids(subfolder.id, result_ids)
  94. else:
  95. result_ids.append(folder_id)
  96. return result_ids
  97. @classmethod
  98. @DB.connection_context()
  99. def create_folder(cls, file, parent_id, name, count):
  100. if count > len(name) - 2:
  101. return file
  102. else:
  103. file = cls.insert({
  104. "id": get_uuid(),
  105. "parent_id": parent_id,
  106. "tenant_id": current_user.id,
  107. "created_by": current_user.id,
  108. "name": name[count],
  109. "location": "",
  110. "size": 0,
  111. "type": FileType.FOLDER
  112. })
  113. return cls.create_folder(file, file.id, name, count + 1)
  114. @classmethod
  115. @DB.connection_context()
  116. def is_parent_folder_exist(cls, parent_id):
  117. parent_files = cls.model.select().where(cls.model.id == parent_id)
  118. if parent_files.count():
  119. return True
  120. cls.delete_folder_by_pf_id(parent_id)
  121. return False
  122. @classmethod
  123. @DB.connection_context()
  124. def get_root_folder(cls, tenant_id):
  125. file = cls.model.select().where(cls.model.tenant_id == tenant_id and
  126. cls.model.parent_id == cls.model.id)
  127. e, file = cls.get_by_id(file[0].id)
  128. if not e:
  129. raise RuntimeError("Database error (File retrieval)!")
  130. return file
  131. @classmethod
  132. @DB.connection_context()
  133. def get_parent_folder(cls, file_id):
  134. file = cls.model.select().where(cls.model.id == file_id)
  135. if file.count():
  136. e, file = cls.get_by_id(file[0].parent_id)
  137. if not e:
  138. raise RuntimeError("Database error (File retrieval)!")
  139. else:
  140. raise RuntimeError("Database error (File doesn't exist)!")
  141. return file
  142. @classmethod
  143. @DB.connection_context()
  144. def get_all_parent_folders(cls, start_id):
  145. parent_folders = []
  146. current_id = start_id
  147. while current_id:
  148. e, file = cls.get_by_id(current_id)
  149. if file.parent_id != file.id and e:
  150. parent_folders.append(file)
  151. current_id = file.parent_id
  152. else:
  153. parent_folders.append(file)
  154. break
  155. return parent_folders
  156. @classmethod
  157. @DB.connection_context()
  158. def insert(cls, file):
  159. if not cls.save(**file):
  160. raise RuntimeError("Database error (File)!")
  161. e, file = cls.get_by_id(file["id"])
  162. if not e:
  163. raise RuntimeError("Database error (File retrieval)!")
  164. return file
  165. @classmethod
  166. @DB.connection_context()
  167. def delete(cls, file):
  168. return cls.delete_by_id(file.id)
  169. @classmethod
  170. @DB.connection_context()
  171. def delete_by_pf_id(cls, folder_id):
  172. return cls.model.delete().where(cls.model.parent_id == folder_id).execute()
  173. @classmethod
  174. @DB.connection_context()
  175. def delete_folder_by_pf_id(cls, user_id, folder_id):
  176. try:
  177. files = cls.model.select().where((cls.model.tenant_id == user_id)
  178. & (cls.model.parent_id == folder_id))
  179. for file in files:
  180. cls.delete_folder_by_pf_id(user_id, file.id)
  181. return cls.model.delete().where((cls.model.tenant_id == user_id)
  182. & (cls.model.id == folder_id)).execute(),
  183. except Exception as e:
  184. print(e)
  185. raise RuntimeError("Database error (File retrieval)!")
  186. @classmethod
  187. @DB.connection_context()
  188. def get_file_count(cls, tenant_id):
  189. files = cls.model.select(cls.model.id).where(cls.model.tenant_id == tenant_id)
  190. return len(files)
  191. @classmethod
  192. @DB.connection_context()
  193. def get_folder_size(cls, folder_id):
  194. size = 0
  195. def dfs(parent_id):
  196. nonlocal size
  197. for f in cls.model.select(*[cls.model.id, cls.model.size, cls.model.type]).where(cls.model.parent_id == parent_id):
  198. size += f.size
  199. if f.type == FileType.FOLDER.value:
  200. dfs(f.id)
  201. dfs(folder_id)
  202. return size