mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 15:29:03 +08:00
Fix: crash of workflow file upload (#10831)
Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: StyleZhang <jasonapring2015@outlook.com>
This commit is contained in:
parent
133de9a087
commit
328965ed7c
@ -16,9 +16,7 @@ class FileUploadConfigManager:
|
|||||||
file_upload_dict = config.get("file_upload")
|
file_upload_dict = config.get("file_upload")
|
||||||
if file_upload_dict:
|
if file_upload_dict:
|
||||||
if file_upload_dict.get("enabled"):
|
if file_upload_dict.get("enabled"):
|
||||||
transform_methods = file_upload_dict.get("allowed_file_upload_methods") or file_upload_dict.get(
|
transform_methods = file_upload_dict.get("allowed_file_upload_methods", [])
|
||||||
"allowed_upload_methods", []
|
|
||||||
)
|
|
||||||
data = {
|
data = {
|
||||||
"image_config": {
|
"image_config": {
|
||||||
"number_limits": file_upload_dict["number_limits"],
|
"number_limits": file_upload_dict["number_limits"],
|
||||||
|
@ -33,8 +33,8 @@ class BaseAppGenerator:
|
|||||||
tenant_id=app_config.tenant_id,
|
tenant_id=app_config.tenant_id,
|
||||||
config=FileUploadConfig(
|
config=FileUploadConfig(
|
||||||
allowed_file_types=entity_dictionary[k].allowed_file_types,
|
allowed_file_types=entity_dictionary[k].allowed_file_types,
|
||||||
allowed_extensions=entity_dictionary[k].allowed_file_extensions,
|
allowed_file_extensions=entity_dictionary[k].allowed_file_extensions,
|
||||||
allowed_upload_methods=entity_dictionary[k].allowed_file_upload_methods,
|
allowed_file_upload_methods=entity_dictionary[k].allowed_file_upload_methods,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
for k, v in user_inputs.items()
|
for k, v in user_inputs.items()
|
||||||
@ -47,8 +47,8 @@ class BaseAppGenerator:
|
|||||||
tenant_id=app_config.tenant_id,
|
tenant_id=app_config.tenant_id,
|
||||||
config=FileUploadConfig(
|
config=FileUploadConfig(
|
||||||
allowed_file_types=entity_dictionary[k].allowed_file_types,
|
allowed_file_types=entity_dictionary[k].allowed_file_types,
|
||||||
allowed_extensions=entity_dictionary[k].allowed_file_extensions,
|
allowed_file_extensions=entity_dictionary[k].allowed_file_extensions,
|
||||||
allowed_upload_methods=entity_dictionary[k].allowed_file_upload_methods,
|
allowed_file_upload_methods=entity_dictionary[k].allowed_file_upload_methods,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
for k, v in user_inputs.items()
|
for k, v in user_inputs.items()
|
||||||
|
@ -28,8 +28,8 @@ class FileUploadConfig(BaseModel):
|
|||||||
|
|
||||||
image_config: Optional[ImageConfig] = None
|
image_config: Optional[ImageConfig] = None
|
||||||
allowed_file_types: Sequence[FileType] = Field(default_factory=list)
|
allowed_file_types: Sequence[FileType] = Field(default_factory=list)
|
||||||
allowed_extensions: Sequence[str] = Field(default_factory=list)
|
allowed_file_extensions: Sequence[str] = Field(default_factory=list)
|
||||||
allowed_upload_methods: Sequence[FileTransferMethod] = Field(default_factory=list)
|
allowed_file_upload_methods: Sequence[FileTransferMethod] = Field(default_factory=list)
|
||||||
number_limits: int = 0
|
number_limits: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -233,10 +233,10 @@ def _is_file_valid_with_config(*, file: File, config: FileUploadConfig) -> bool:
|
|||||||
if config.allowed_file_types and file.type not in config.allowed_file_types and file.type != FileType.CUSTOM:
|
if config.allowed_file_types and file.type not in config.allowed_file_types and file.type != FileType.CUSTOM:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if config.allowed_extensions and file.extension not in config.allowed_extensions:
|
if config.allowed_file_extensions and file.extension not in config.allowed_file_extensions:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if config.allowed_upload_methods and file.transfer_method not in config.allowed_upload_methods:
|
if config.allowed_file_upload_methods and file.transfer_method not in config.allowed_file_upload_methods:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if file.type == FileType.IMAGE and config.image_config:
|
if file.type == FileType.IMAGE and config.image_config:
|
||||||
|
@ -169,9 +169,9 @@ class Workflow(db.Model):
|
|||||||
)
|
)
|
||||||
features["file_upload"]["enabled"] = image_enabled
|
features["file_upload"]["enabled"] = image_enabled
|
||||||
features["file_upload"]["number_limits"] = image_number_limits
|
features["file_upload"]["number_limits"] = image_number_limits
|
||||||
features["file_upload"]["allowed_upload_methods"] = image_transfer_methods
|
features["file_upload"]["allowed_file_upload_methods"] = image_transfer_methods
|
||||||
features["file_upload"]["allowed_file_types"] = ["image"]
|
features["file_upload"]["allowed_file_types"] = ["image"]
|
||||||
features["file_upload"]["allowed_extensions"] = []
|
features["file_upload"]["allowed_file_extensions"] = []
|
||||||
del features["file_upload"]["image"]
|
del features["file_upload"]["image"]
|
||||||
self._features = json.dumps(features)
|
self._features = json.dumps(features)
|
||||||
return self._features
|
return self._features
|
||||||
|
@ -27,8 +27,8 @@ NEW_VERSION_WORKFLOW_FEATURES = {
|
|||||||
"file_upload": {
|
"file_upload": {
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"allowed_file_types": ["image"],
|
"allowed_file_types": ["image"],
|
||||||
"allowed_extensions": [],
|
"allowed_file_extensions": [],
|
||||||
"allowed_upload_methods": ["remote_url", "local_file"],
|
"allowed_file_upload_methods": ["remote_url", "local_file"],
|
||||||
"number_limits": 6,
|
"number_limits": 6,
|
||||||
},
|
},
|
||||||
"opening_statement": "",
|
"opening_statement": "",
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
from core.file import FILE_MODEL_IDENTITY, File, FileTransferMethod, FileType
|
import json
|
||||||
|
|
||||||
|
from core.file import FILE_MODEL_IDENTITY, File, FileTransferMethod, FileType, FileUploadConfig
|
||||||
|
from models.workflow import Workflow
|
||||||
|
|
||||||
|
|
||||||
def test_file_loads_and_dumps():
|
def test_file_loads_and_dumps():
|
||||||
@ -38,3 +41,40 @@ def test_file_to_dict():
|
|||||||
file_dict = file.to_dict()
|
file_dict = file.to_dict()
|
||||||
assert "_extra_config" not in file_dict
|
assert "_extra_config" not in file_dict
|
||||||
assert "url" in file_dict
|
assert "url" in file_dict
|
||||||
|
|
||||||
|
|
||||||
|
def test_workflow_features_with_image():
|
||||||
|
# Create a feature dict that mimics the old structure with image config
|
||||||
|
features = {
|
||||||
|
"file_upload": {
|
||||||
|
"image": {"enabled": True, "number_limits": 5, "transfer_methods": ["remote_url", "local_file"]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a workflow instance with the features
|
||||||
|
workflow = Workflow(
|
||||||
|
tenant_id="tenant-1",
|
||||||
|
app_id="app-1",
|
||||||
|
type="chat",
|
||||||
|
version="1.0",
|
||||||
|
graph="{}",
|
||||||
|
features=json.dumps(features),
|
||||||
|
created_by="user-1",
|
||||||
|
environment_variables=[],
|
||||||
|
conversation_variables=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the converted features through the property
|
||||||
|
converted_features = json.loads(workflow.features)
|
||||||
|
|
||||||
|
# Create FileUploadConfig from the converted features
|
||||||
|
file_upload_config = FileUploadConfig.model_validate(converted_features["file_upload"])
|
||||||
|
|
||||||
|
# Validate the config
|
||||||
|
assert file_upload_config.number_limits == 5
|
||||||
|
assert list(file_upload_config.allowed_file_types) == [FileType.IMAGE]
|
||||||
|
assert list(file_upload_config.allowed_file_upload_methods) == [
|
||||||
|
FileTransferMethod.REMOTE_URL,
|
||||||
|
FileTransferMethod.LOCAL_FILE,
|
||||||
|
]
|
||||||
|
assert list(file_upload_config.allowed_file_extensions) == []
|
||||||
|
@ -44,21 +44,24 @@ export const fileUpload: FileUpload = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getFileExtension = (fileName: string, fileMimetype: string, isRemote?: boolean) => {
|
export const getFileExtension = (fileName: string, fileMimetype: string, isRemote?: boolean) => {
|
||||||
|
let extension = ''
|
||||||
if (fileMimetype)
|
if (fileMimetype)
|
||||||
return mime.getExtension(fileMimetype) || ''
|
extension = mime.getExtension(fileMimetype) || ''
|
||||||
|
|
||||||
if (isRemote)
|
if (fileName && !extension) {
|
||||||
return ''
|
|
||||||
|
|
||||||
if (fileName) {
|
|
||||||
const fileNamePair = fileName.split('.')
|
const fileNamePair = fileName.split('.')
|
||||||
const fileNamePairLength = fileNamePair.length
|
const fileNamePairLength = fileNamePair.length
|
||||||
|
|
||||||
if (fileNamePairLength > 1)
|
if (fileNamePairLength > 1)
|
||||||
return fileNamePair[fileNamePairLength - 1]
|
extension = fileNamePair[fileNamePairLength - 1]
|
||||||
|
else
|
||||||
|
extension = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return ''
|
if (isRemote)
|
||||||
|
extension = ''
|
||||||
|
|
||||||
|
return extension
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFileAppearanceType = (fileName: string, fileMimetype: string) => {
|
export const getFileAppearanceType = (fileName: string, fileMimetype: string) => {
|
||||||
|
@ -391,7 +391,7 @@ const TextGeneration: FC<IMainProps> = ({
|
|||||||
setVisionConfig({
|
setVisionConfig({
|
||||||
// legacy of image upload compatible
|
// legacy of image upload compatible
|
||||||
...file_upload,
|
...file_upload,
|
||||||
transfer_methods: file_upload.allowed_upload_methods,
|
transfer_methods: file_upload.allowed_file_upload_methods || file_upload.allowed_upload_methods,
|
||||||
// legacy of image upload compatible
|
// legacy of image upload compatible
|
||||||
image_file_size_limit: appParams?.system_parameters?.image_file_size_limit,
|
image_file_size_limit: appParams?.system_parameters?.image_file_size_limit,
|
||||||
fileUploadConfig: appParams?.system_parameters,
|
fileUploadConfig: appParams?.system_parameters,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user