Add files router to API v1
This commit is contained in:
parent
2ee9e5bb97
commit
4b08504ff7
3 changed files with 29 additions and 30 deletions
|
|
@ -6,6 +6,7 @@ from langflow.api.v1 import (
|
||||||
chat_router,
|
chat_router,
|
||||||
credentials_router,
|
credentials_router,
|
||||||
endpoints_router,
|
endpoints_router,
|
||||||
|
files_router,
|
||||||
flows_router,
|
flows_router,
|
||||||
login_router,
|
login_router,
|
||||||
store_router,
|
store_router,
|
||||||
|
|
@ -25,3 +26,4 @@ router.include_router(users_router)
|
||||||
router.include_router(api_key_router)
|
router.include_router(api_key_router)
|
||||||
router.include_router(login_router)
|
router.include_router(login_router)
|
||||||
router.include_router(credentials_router)
|
router.include_router(credentials_router)
|
||||||
|
router.include_router(files_router)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from langflow.api.v1.api_key import router as api_key_router
|
||||||
from langflow.api.v1.chat import router as chat_router
|
from langflow.api.v1.chat import router as chat_router
|
||||||
from langflow.api.v1.credential import router as credentials_router
|
from langflow.api.v1.credential import router as credentials_router
|
||||||
from langflow.api.v1.endpoints import router as endpoints_router
|
from langflow.api.v1.endpoints import router as endpoints_router
|
||||||
|
from langflow.api.v1.files import router as files_router
|
||||||
from langflow.api.v1.flows import router as flows_router
|
from langflow.api.v1.flows import router as flows_router
|
||||||
from langflow.api.v1.login import router as login_router
|
from langflow.api.v1.login import router as login_router
|
||||||
from langflow.api.v1.store import router as store_router
|
from langflow.api.v1.store import router as store_router
|
||||||
|
|
@ -18,4 +19,5 @@ __all__ = [
|
||||||
"api_key_router",
|
"api_key_router",
|
||||||
"login_router",
|
"login_router",
|
||||||
"credentials_router",
|
"credentials_router",
|
||||||
|
"files_router",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,22 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from pathlib import Path
|
from io import BytesIO
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile
|
from fastapi import APIRouter, Depends, HTTPException, UploadFile
|
||||||
|
from fastapi.responses import StreamingResponse
|
||||||
|
|
||||||
from langflow.services.deps import get_storage_service
|
from langflow.services.deps import get_storage_service
|
||||||
from langflow.services.storage.service import StorageService
|
from langflow.services.storage.service import StorageService
|
||||||
|
from langflow.services.storage.utils import build_content_type_from_extension
|
||||||
|
|
||||||
router = APIRouter(tags=["Files"], prefix="/files")
|
router = APIRouter(tags=["Files"], prefix="/files")
|
||||||
|
|
||||||
|
|
||||||
@router.post("/upload/{folder}", status_code=HTTPStatus.CREATED)
|
@router.post("/upload/{flow_id}", status_code=HTTPStatus.CREATED)
|
||||||
async def upload_file(flow_id: str, file: UploadFile, storage_service: StorageService = Depends(get_storage_service)):
|
async def upload_file(flow_id: str, file: UploadFile, storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
file_content = await file.read()
|
file_content = await file.read()
|
||||||
file_name = file.filename
|
file_name = file.filename or hashlib.sha256(file_content).hexdigest()
|
||||||
filename = file.filename
|
|
||||||
if isinstance(filename, str) or isinstance(filename, Path):
|
|
||||||
file_extension = Path(filename).suffix
|
|
||||||
else:
|
|
||||||
file_extension = ""
|
|
||||||
file_object = file.file
|
|
||||||
sha256_hash = hashlib.sha256()
|
|
||||||
# Reset the file cursor to the beginning of the file
|
|
||||||
file_object.seek(0)
|
|
||||||
# Iterate over the uploaded file in small chunks to conserve memory
|
|
||||||
while chunk := file_object.read(8192): # Read 8KB at a time (adjust as needed)
|
|
||||||
sha256_hash.update(chunk)
|
|
||||||
|
|
||||||
# Use the hex digest of the hash as the file name
|
|
||||||
hex_dig = sha256_hash.hexdigest()
|
|
||||||
file_name = f"{hex_dig}{file_extension}"
|
|
||||||
|
|
||||||
folder = flow_id
|
folder = flow_id
|
||||||
storage_service.save_file(folder=folder, file_name=file_name, data=file_content)
|
storage_service.save_file(folder=folder, file_name=file_name, data=file_content)
|
||||||
return {"message": "File uploaded successfully", "file_path": f"{folder}/{file.filename}"}
|
return {"message": "File uploaded successfully", "file_path": f"{folder}/{file.filename}"}
|
||||||
|
|
@ -39,28 +24,38 @@ async def upload_file(flow_id: str, file: UploadFile, storage_service: StorageSe
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
@router.get("/download/{folder}/{file_name}")
|
@router.get("/download/{flow_id}/{file_name}")
|
||||||
async def download_file(folder: str, file_name: str, storage_service: StorageService = Depends(get_storage_service)):
|
async def download_file(flow_id: str, file_name: str, storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
file_content = storage_service.get_file(folder=folder, file_name=file_name)
|
extension = file_name.split(".")[-1]
|
||||||
return {"file_content": file_content}
|
|
||||||
|
if not extension:
|
||||||
|
raise HTTPException(status_code=500, detail=f"Extension not found for file {file_name}")
|
||||||
|
|
||||||
|
content_type = build_content_type_from_extension(extension)
|
||||||
|
|
||||||
|
if not content_type:
|
||||||
|
raise HTTPException(status_code=500, detail=f"Content type not found for extension {extension}")
|
||||||
|
|
||||||
|
file_content = storage_service.get_file(folder=flow_id, file_name=file_name)
|
||||||
|
return StreamingResponse(BytesIO(file_content), media_type=content_type)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
@router.get("/list/{folder}")
|
@router.get("/list/{flow_id}")
|
||||||
async def list_files(folder: str, storage_service: StorageService = Depends(get_storage_service)):
|
async def list_files(flow_id: str, storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
files = storage_service.list_files(folder=folder)
|
files = storage_service.list_files(folder=flow_id)
|
||||||
return {"files": files}
|
return {"files": files}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/delete/{folder}/{file_name}")
|
@router.delete("/delete/{flow_id}/{file_name}")
|
||||||
async def delete_file(folder: str, file_name: str, storage_service: StorageService = Depends(get_storage_service)):
|
async def delete_file(flow_id: str, file_name: str, storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
storage_service.delete_file(folder=folder, file_name=file_name)
|
storage_service.delete_file(folder=flow_id, file_name=file_name)
|
||||||
return {"message": f"File {file_name} deleted successfully"}
|
return {"message": f"File {file_name} deleted successfully"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue