diff --git a/src/backend/langflow/api/endpoints.py b/src/backend/langflow/api/endpoints.py index 021a81ca8..2d4e96abf 100644 --- a/src/backend/langflow/api/endpoints.py +++ b/src/backend/langflow/api/endpoints.py @@ -1,7 +1,7 @@ import logging from importlib.metadata import version -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, UploadFile from langflow.api.schemas import ( ExportedFlow, @@ -9,6 +9,7 @@ from langflow.api.schemas import ( PredictRequest, PredictResponse, ) +from langflow.cache.base import save_uploaded_file from langflow.interface.run import process_graph_cached from langflow.interface.types import build_langchain_types_dict @@ -36,6 +37,15 @@ async def get_load(predict_request: PredictRequest): raise HTTPException(status_code=500, detail=str(e)) from e +# Endpoint to upload file +@router.post("/upload/{client_id}") +async def create_upload_file(file: UploadFile, client_id: str): + # Cache file + file_path = save_uploaded_file(file.file, file_name=client_id) + + return {"filename": file_path} + + # get endpoint to return version of langflow @router.get("/version") def get_version(): diff --git a/src/backend/langflow/api/validate.py b/src/backend/langflow/api/validate.py index 0e2a7752c..4d397b8b4 100644 --- a/src/backend/langflow/api/validate.py +++ b/src/backend/langflow/api/validate.py @@ -51,7 +51,12 @@ def post_validate_node(node_id: str, data: dict): raise ValueError(f"Node {node_id} not found") if not isinstance(node, VectorStoreNode): node.build() - return json.dumps({"valid": True, "params": str(node._built_object_repr())}) + return json.dumps( + { + "valid": True, + "params": f"{str(node._built_object_repr())[:300]}...", + } + ) except Exception as e: logger.exception(e) return json.dumps({"valid": False, "params": str(e)}) diff --git a/src/backend/langflow/cache/base.py b/src/backend/langflow/cache/base.py index 0f1ff5d92..f5ef69bc4 100644 --- a/src/backend/langflow/cache/base.py +++ b/src/backend/langflow/cache/base.py @@ -135,6 +135,19 @@ def save_binary_file(content: str, file_name: str, accepted_types: list[str]) -> return file_path +@create_cache_folder +def save_uploaded_file(file, file_name): + cache_path = Path(tempfile.gettempdir()) / PREFIX + file_path = cache_path / file_name + + with open(file_path, "wb") as new_file: + # Iterate over the uploaded file in small chunks to conserve memory + while chunk := file.read(8192): # Read 8KB at a time (adjust as needed) + new_file.write(chunk) + + return file_path + + @create_cache_folder def save_cache(hash_val: str, chat_data, clean_old_cache_files: bool): cache_path = Path(tempfile.gettempdir()) / PREFIX / f"{hash_val}.dill" diff --git a/src/backend/langflow/graph/base.py b/src/backend/langflow/graph/base.py index cc5e2902b..3e048e4f6 100644 --- a/src/backend/langflow/graph/base.py +++ b/src/backend/langflow/graph/base.py @@ -87,12 +87,7 @@ class Node: # Load the type in value.get('suffixes') using # what is inside value.get('content') # value.get('value') is the file name - file_name = value.get("value") - content = value.get("content") - type_to_load = value.get("suffixes") - file_path = cache_utils.save_binary_file( - content=content, file_name=file_name, accepted_types=type_to_load - ) + file_path = value.get("file_path") params[key] = file_path diff --git a/src/backend/langflow/template/field/base.py b/src/backend/langflow/template/field/base.py index a1de2c1b6..a9c18ff63 100644 --- a/src/backend/langflow/template/field/base.py +++ b/src/backend/langflow/template/field/base.py @@ -15,7 +15,7 @@ class TemplateFieldCreator(BaseModel, ABC): suffixes: list[str] = [] fileTypes: list[str] = [] file_types: list[str] = [] - content: Union[str, None] = None + file_path: Union[str, None] = None password: bool = False options: list[str] = [] name: str = "" @@ -35,7 +35,7 @@ class TemplateFieldCreator(BaseModel, ABC): result["fileTypes"] = result.pop("file_types") if self.field_type == "file": - result["content"] = self.content + result["file_path"] = self.file_path return result