files.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. import logging
  2. import os
  3. import shutil
  4. import uuid
  5. from pathlib import Path
  6. from typing import Optional
  7. from open_webui.apps.webui.models.files import FileForm, FileModel, Files
  8. from open_webui.apps.webui.models.knowledge import Knowledges
  9. from open_webui.config import UPLOAD_DIR
  10. from open_webui.constants import ERROR_MESSAGES
  11. from open_webui.env import SRC_LOG_LEVELS
  12. from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
  13. from fastapi.responses import FileResponse, StreamingResponse
  14. from open_webui.utils.utils import get_admin_user, get_verified_user
  15. log = logging.getLogger(__name__)
  16. log.setLevel(SRC_LOG_LEVELS["MODELS"])
  17. router = APIRouter()
  18. ############################
  19. # Upload File
  20. ############################
  21. @router.post("/")
  22. def upload_file(file: UploadFile = File(...), user=Depends(get_verified_user)):
  23. log.info(f"file.content_type: {file.content_type}")
  24. try:
  25. unsanitized_filename = file.filename
  26. filename = os.path.basename(unsanitized_filename)
  27. # replace filename with uuid
  28. id = str(uuid.uuid4())
  29. name = filename
  30. filename = f"{id}_{filename}"
  31. file_path = f"{UPLOAD_DIR}/{filename}"
  32. contents = file.file.read()
  33. with open(file_path, "wb") as f:
  34. f.write(contents)
  35. f.close()
  36. file = Files.insert_new_file(
  37. user.id,
  38. FileForm(
  39. **{
  40. "id": id,
  41. "filename": filename,
  42. "meta": {
  43. "name": name,
  44. "content_type": file.content_type,
  45. "size": len(contents),
  46. "path": file_path,
  47. },
  48. }
  49. ),
  50. )
  51. if file:
  52. return file
  53. else:
  54. raise HTTPException(
  55. status_code=status.HTTP_400_BAD_REQUEST,
  56. detail=ERROR_MESSAGES.DEFAULT("Error uploading file"),
  57. )
  58. except Exception as e:
  59. log.exception(e)
  60. raise HTTPException(
  61. status_code=status.HTTP_400_BAD_REQUEST,
  62. detail=ERROR_MESSAGES.DEFAULT(e),
  63. )
  64. ############################
  65. # List Files
  66. ############################
  67. @router.get("/", response_model=list[FileModel])
  68. async def list_files(user=Depends(get_verified_user)):
  69. if user.role == "admin":
  70. files = Files.get_files()
  71. else:
  72. files = Files.get_files_by_user_id(user.id)
  73. return files
  74. ############################
  75. # Delete All Files
  76. ############################
  77. @router.delete("/all")
  78. async def delete_all_files(user=Depends(get_admin_user)):
  79. result = Files.delete_all_files()
  80. if result:
  81. folder = f"{UPLOAD_DIR}"
  82. try:
  83. # Check if the directory exists
  84. if os.path.exists(folder):
  85. # Iterate over all the files and directories in the specified directory
  86. for filename in os.listdir(folder):
  87. file_path = os.path.join(folder, filename)
  88. try:
  89. if os.path.isfile(file_path) or os.path.islink(file_path):
  90. os.unlink(file_path) # Remove the file or link
  91. elif os.path.isdir(file_path):
  92. shutil.rmtree(file_path) # Remove the directory
  93. except Exception as e:
  94. print(f"Failed to delete {file_path}. Reason: {e}")
  95. else:
  96. print(f"The directory {folder} does not exist")
  97. except Exception as e:
  98. print(f"Failed to process the directory {folder}. Reason: {e}")
  99. return {"message": "All files deleted successfully"}
  100. else:
  101. raise HTTPException(
  102. status_code=status.HTTP_400_BAD_REQUEST,
  103. detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
  104. )
  105. ############################
  106. # Get File By Id
  107. ############################
  108. @router.get("/{id}", response_model=Optional[FileModel])
  109. async def get_file_by_id(id: str, user=Depends(get_verified_user)):
  110. file = Files.get_file_by_id(id)
  111. if file and (file.user_id == user.id or user.role == "admin"):
  112. return file
  113. else:
  114. raise HTTPException(
  115. status_code=status.HTTP_404_NOT_FOUND,
  116. detail=ERROR_MESSAGES.NOT_FOUND,
  117. )
  118. ############################
  119. # Get File Content By Id
  120. ############################
  121. @router.get("/{id}/content", response_model=Optional[FileModel])
  122. async def get_file_content_by_id(id: str, user=Depends(get_verified_user)):
  123. file = Files.get_file_by_id(id)
  124. if file and (file.user_id == user.id or user.role == "admin"):
  125. file_path = Path(file.meta["path"])
  126. # Check if the file already exists in the cache
  127. if file_path.is_file():
  128. print(f"file_path: {file_path}")
  129. return FileResponse(file_path)
  130. else:
  131. raise HTTPException(
  132. status_code=status.HTTP_404_NOT_FOUND,
  133. detail=ERROR_MESSAGES.NOT_FOUND,
  134. )
  135. else:
  136. raise HTTPException(
  137. status_code=status.HTTP_404_NOT_FOUND,
  138. detail=ERROR_MESSAGES.NOT_FOUND,
  139. )
  140. @router.get("/{id}/content/text")
  141. async def get_file_text_content_by_id(id: str, user=Depends(get_verified_user)):
  142. file = Files.get_file_by_id(id)
  143. if file and (file.user_id == user.id or user.role == "admin"):
  144. return {"text": file.data.get("content")}
  145. else:
  146. raise HTTPException(
  147. status_code=status.HTTP_404_NOT_FOUND,
  148. detail=ERROR_MESSAGES.NOT_FOUND,
  149. )
  150. @router.get("/{id}/content/{file_name}", response_model=Optional[FileModel])
  151. async def get_file_content_by_id(id: str, user=Depends(get_verified_user)):
  152. file = Files.get_file_by_id(id)
  153. if file and (file.user_id == user.id or user.role == "admin"):
  154. file_path = file.meta.get("path")
  155. if file_path:
  156. file_path = Path(file_path)
  157. # Check if the file already exists in the cache
  158. if file_path.is_file():
  159. print(f"file_path: {file_path}")
  160. return FileResponse(file_path)
  161. else:
  162. raise HTTPException(
  163. status_code=status.HTTP_404_NOT_FOUND,
  164. detail=ERROR_MESSAGES.NOT_FOUND,
  165. )
  166. else:
  167. # File path doesn’t exist, return the content as .txt if possible
  168. file_content = file.content.get("content", "")
  169. file_name = file.filename
  170. # Create a generator that encodes the file content
  171. def generator():
  172. yield file_content.encode("utf-8")
  173. return StreamingResponse(
  174. generator(),
  175. media_type="text/plain",
  176. headers={"Content-Disposition": f"attachment; filename={file_name}"},
  177. )
  178. else:
  179. raise HTTPException(
  180. status_code=status.HTTP_404_NOT_FOUND,
  181. detail=ERROR_MESSAGES.NOT_FOUND,
  182. )
  183. ############################
  184. # Delete File By Id
  185. ############################
  186. @router.delete("/{id}")
  187. async def delete_file_by_id(id: str, user=Depends(get_verified_user)):
  188. file = Files.get_file_by_id(id)
  189. if file and (file.user_id == user.id or user.role == "admin"):
  190. result = Files.delete_file_by_id(id)
  191. if result:
  192. return {"message": "File deleted successfully"}
  193. else:
  194. raise HTTPException(
  195. status_code=status.HTTP_400_BAD_REQUEST,
  196. detail=ERROR_MESSAGES.DEFAULT("Error deleting file"),
  197. )
  198. else:
  199. raise HTTPException(
  200. status_code=status.HTTP_404_NOT_FOUND,
  201. detail=ERROR_MESSAGES.NOT_FOUND,
  202. )