Parcourir la source

feat(workflow): add configurable workflow file upload limit (#10176)

Co-authored-by: JzoNg <jzongcode@gmail.com>
tags/0.11.0
-LAN- il y a 1 an
Parent
révision
6452342222
Aucun compte lié à l'adresse e-mail de l'auteur

+ 3
- 0
api/.env.example Voir le fichier

BATCH_UPLOAD_LIMIT=10 BATCH_UPLOAD_LIMIT=10
KEYWORD_DATA_SOURCE_TYPE=database KEYWORD_DATA_SOURCE_TYPE=database


# Workflow file upload limit
WORKFLOW_FILE_UPLOAD_LIMIT=10

# CODE EXECUTION CONFIGURATION # CODE EXECUTION CONFIGURATION
CODE_EXECUTION_ENDPOINT=http://127.0.0.1:8194 CODE_EXECUTION_ENDPOINT=http://127.0.0.1:8194
CODE_EXECUTION_API_KEY=dify-sandbox CODE_EXECUTION_API_KEY=dify-sandbox

+ 5
- 0
api/configs/feature/__init__.py Voir le fichier

default=20, default=20,
) )


WORKFLOW_FILE_UPLOAD_LIMIT: PositiveInt = Field(
description="Maximum number of files allowed in a workflow upload operation",
default=10,
)



class HttpConfig(BaseSettings): class HttpConfig(BaseSettings):
""" """

+ 24
- 0
api/controllers/common/fields.py Voir le fichier

from flask_restful import fields

parameters__system_parameters = {
"image_file_size_limit": fields.Integer,
"video_file_size_limit": fields.Integer,
"audio_file_size_limit": fields.Integer,
"file_size_limit": fields.Integer,
"workflow_file_upload_limit": fields.Integer,
}

parameters_fields = {
"opening_statement": fields.String,
"suggested_questions": fields.Raw,
"suggested_questions_after_answer": fields.Raw,
"speech_to_text": fields.Raw,
"text_to_speech": fields.Raw,
"retriever_resource": fields.Raw,
"annotation_reply": fields.Raw,
"more_like_this": fields.Raw,
"user_input_form": fields.Raw,
"sensitive_word_avoidance": fields.Raw,
"file_upload": fields.Raw,
"system_parameters": fields.Nested(parameters__system_parameters),
}

+ 39
- 0
api/controllers/common/helpers.py Voir le fichier

import os import os
import re import re
import urllib.parse import urllib.parse
from collections.abc import Mapping
from typing import Any
from uuid import uuid4 from uuid import uuid4


import httpx import httpx
from pydantic import BaseModel from pydantic import BaseModel


from configs import dify_config



class FileInfo(BaseModel): class FileInfo(BaseModel):
filename: str filename: str
mimetype=mimetype, mimetype=mimetype,
size=int(response.headers.get("Content-Length", -1)), size=int(response.headers.get("Content-Length", -1)),
) )


def get_parameters_from_feature_dict(*, features_dict: Mapping[str, Any], user_input_form: list[dict[str, Any]]):
return {
"opening_statement": features_dict.get("opening_statement"),
"suggested_questions": features_dict.get("suggested_questions", []),
"suggested_questions_after_answer": features_dict.get("suggested_questions_after_answer", {"enabled": False}),
"speech_to_text": features_dict.get("speech_to_text", {"enabled": False}),
"text_to_speech": features_dict.get("text_to_speech", {"enabled": False}),
"retriever_resource": features_dict.get("retriever_resource", {"enabled": False}),
"annotation_reply": features_dict.get("annotation_reply", {"enabled": False}),
"more_like_this": features_dict.get("more_like_this", {"enabled": False}),
"user_input_form": user_input_form,
"sensitive_word_avoidance": features_dict.get(
"sensitive_word_avoidance", {"enabled": False, "type": "", "configs": []}
),
"file_upload": features_dict.get(
"file_upload",
{
"image": {
"enabled": False,
"number_limits": 3,
"detail": "high",
"transfer_methods": ["remote_url", "local_file"],
}
},
),
"system_parameters": {
"image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
"video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
"audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
"file_size_limit": dify_config.UPLOAD_FILE_SIZE_LIMIT,
"workflow_file_upload_limit": dify_config.WORKFLOW_FILE_UPLOAD_LIMIT,
},
}

+ 13
- 68
api/controllers/console/explore/parameter.py Voir le fichier

from flask_restful import fields, marshal_with
from flask_restful import marshal_with


from configs import dify_config
from controllers.common import fields
from controllers.common import helpers as controller_helpers
from controllers.console import api from controllers.console import api
from controllers.console.app.error import AppUnavailableError from controllers.console.app.error import AppUnavailableError
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
class AppParameterApi(InstalledAppResource): class AppParameterApi(InstalledAppResource):
"""Resource for app variables.""" """Resource for app variables."""


variable_fields = {
"key": fields.String,
"name": fields.String,
"description": fields.String,
"type": fields.String,
"default": fields.String,
"max_length": fields.Integer,
"options": fields.List(fields.String),
}

system_parameters_fields = {
"image_file_size_limit": fields.Integer,
"video_file_size_limit": fields.Integer,
"audio_file_size_limit": fields.Integer,
"file_size_limit": fields.Integer,
}

parameters_fields = {
"opening_statement": fields.String,
"suggested_questions": fields.Raw,
"suggested_questions_after_answer": fields.Raw,
"speech_to_text": fields.Raw,
"text_to_speech": fields.Raw,
"retriever_resource": fields.Raw,
"annotation_reply": fields.Raw,
"more_like_this": fields.Raw,
"user_input_form": fields.Raw,
"sensitive_word_avoidance": fields.Raw,
"file_upload": fields.Raw,
"system_parameters": fields.Nested(system_parameters_fields),
}

@marshal_with(parameters_fields)
@marshal_with(fields.parameters_fields)
def get(self, installed_app: InstalledApp): def get(self, installed_app: InstalledApp):
"""Retrieve app parameters.""" """Retrieve app parameters."""
app_model = installed_app.app app_model = installed_app.app


if app_model is None:
raise AppUnavailableError()

if app_model.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}: if app_model.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}:
workflow = app_model.workflow workflow = app_model.workflow
if workflow is None: if workflow is None:
user_input_form = workflow.user_input_form(to_old_structure=True) user_input_form = workflow.user_input_form(to_old_structure=True)
else: else:
app_model_config = app_model.app_model_config app_model_config = app_model.app_model_config
if app_model_config is None:
raise AppUnavailableError()

features_dict = app_model_config.to_dict() features_dict = app_model_config.to_dict()


user_input_form = features_dict.get("user_input_form", []) user_input_form = features_dict.get("user_input_form", [])


return {
"opening_statement": features_dict.get("opening_statement"),
"suggested_questions": features_dict.get("suggested_questions", []),
"suggested_questions_after_answer": features_dict.get(
"suggested_questions_after_answer", {"enabled": False}
),
"speech_to_text": features_dict.get("speech_to_text", {"enabled": False}),
"text_to_speech": features_dict.get("text_to_speech", {"enabled": False}),
"retriever_resource": features_dict.get("retriever_resource", {"enabled": False}),
"annotation_reply": features_dict.get("annotation_reply", {"enabled": False}),
"more_like_this": features_dict.get("more_like_this", {"enabled": False}),
"user_input_form": user_input_form,
"sensitive_word_avoidance": features_dict.get(
"sensitive_word_avoidance", {"enabled": False, "type": "", "configs": []}
),
"file_upload": features_dict.get(
"file_upload",
{
"image": {
"enabled": False,
"number_limits": 3,
"detail": "high",
"transfer_methods": ["remote_url", "local_file"],
}
},
),
"system_parameters": {
"image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
"video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
"audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
"file_size_limit": dify_config.UPLOAD_FILE_SIZE_LIMIT,
},
}
return controller_helpers.get_parameters_from_feature_dict(
features_dict=features_dict, user_input_form=user_input_form
)




class ExploreAppMetaApi(InstalledAppResource): class ExploreAppMetaApi(InstalledAppResource):

+ 1
- 0
api/controllers/console/files/__init__.py Voir le fichier

"image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT, "image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
"video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT, "video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
"audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT, "audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
"workflow_file_upload_limit": dify_config.WORKFLOW_FILE_UPLOAD_LIMIT,
}, 200 }, 200


@setup_required @setup_required

+ 10
- 68
api/controllers/service_api/app/app.py Voir le fichier

from flask_restful import Resource, fields, marshal_with
from flask_restful import Resource, marshal_with


from configs import dify_config
from controllers.common import fields
from controllers.common import helpers as controller_helpers
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app.error import AppUnavailableError from controllers.service_api.app.error import AppUnavailableError
from controllers.service_api.wraps import validate_app_token from controllers.service_api.wraps import validate_app_token
class AppParameterApi(Resource): class AppParameterApi(Resource):
"""Resource for app variables.""" """Resource for app variables."""


variable_fields = {
"key": fields.String,
"name": fields.String,
"description": fields.String,
"type": fields.String,
"default": fields.String,
"max_length": fields.Integer,
"options": fields.List(fields.String),
}

system_parameters_fields = {
"image_file_size_limit": fields.Integer,
"video_file_size_limit": fields.Integer,
"audio_file_size_limit": fields.Integer,
"file_size_limit": fields.Integer,
}

parameters_fields = {
"opening_statement": fields.String,
"suggested_questions": fields.Raw,
"suggested_questions_after_answer": fields.Raw,
"speech_to_text": fields.Raw,
"text_to_speech": fields.Raw,
"retriever_resource": fields.Raw,
"annotation_reply": fields.Raw,
"more_like_this": fields.Raw,
"user_input_form": fields.Raw,
"sensitive_word_avoidance": fields.Raw,
"file_upload": fields.Raw,
"system_parameters": fields.Nested(system_parameters_fields),
}

@validate_app_token @validate_app_token
@marshal_with(parameters_fields)
@marshal_with(fields.parameters_fields)
def get(self, app_model: App): def get(self, app_model: App):
"""Retrieve app parameters.""" """Retrieve app parameters."""
if app_model.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}: if app_model.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}:
user_input_form = workflow.user_input_form(to_old_structure=True) user_input_form = workflow.user_input_form(to_old_structure=True)
else: else:
app_model_config = app_model.app_model_config app_model_config = app_model.app_model_config
if app_model_config is None:
raise AppUnavailableError()

features_dict = app_model_config.to_dict() features_dict = app_model_config.to_dict()


user_input_form = features_dict.get("user_input_form", []) user_input_form = features_dict.get("user_input_form", [])


return {
"opening_statement": features_dict.get("opening_statement"),
"suggested_questions": features_dict.get("suggested_questions", []),
"suggested_questions_after_answer": features_dict.get(
"suggested_questions_after_answer", {"enabled": False}
),
"speech_to_text": features_dict.get("speech_to_text", {"enabled": False}),
"text_to_speech": features_dict.get("text_to_speech", {"enabled": False}),
"retriever_resource": features_dict.get("retriever_resource", {"enabled": False}),
"annotation_reply": features_dict.get("annotation_reply", {"enabled": False}),
"more_like_this": features_dict.get("more_like_this", {"enabled": False}),
"user_input_form": user_input_form,
"sensitive_word_avoidance": features_dict.get(
"sensitive_word_avoidance", {"enabled": False, "type": "", "configs": []}
),
"file_upload": features_dict.get(
"file_upload",
{
"image": {
"enabled": False,
"number_limits": 3,
"detail": "high",
"transfer_methods": ["remote_url", "local_file"],
}
},
),
"system_parameters": {
"image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
"video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
"audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
"file_size_limit": dify_config.UPLOAD_FILE_SIZE_LIMIT,
},
}
return controller_helpers.get_parameters_from_feature_dict(
features_dict=features_dict, user_input_form=user_input_form
)




class AppMetaApi(Resource): class AppMetaApi(Resource):

+ 10
- 68
api/controllers/web/app.py Voir le fichier

from flask_restful import fields, marshal_with
from flask_restful import marshal_with


from configs import dify_config
from controllers.common import fields
from controllers.common import helpers as controller_helpers
from controllers.web import api from controllers.web import api
from controllers.web.error import AppUnavailableError from controllers.web.error import AppUnavailableError
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
class AppParameterApi(WebApiResource): class AppParameterApi(WebApiResource):
"""Resource for app variables.""" """Resource for app variables."""


variable_fields = {
"key": fields.String,
"name": fields.String,
"description": fields.String,
"type": fields.String,
"default": fields.String,
"max_length": fields.Integer,
"options": fields.List(fields.String),
}

system_parameters_fields = {
"image_file_size_limit": fields.Integer,
"video_file_size_limit": fields.Integer,
"audio_file_size_limit": fields.Integer,
"file_size_limit": fields.Integer,
}

parameters_fields = {
"opening_statement": fields.String,
"suggested_questions": fields.Raw,
"suggested_questions_after_answer": fields.Raw,
"speech_to_text": fields.Raw,
"text_to_speech": fields.Raw,
"retriever_resource": fields.Raw,
"annotation_reply": fields.Raw,
"more_like_this": fields.Raw,
"user_input_form": fields.Raw,
"sensitive_word_avoidance": fields.Raw,
"file_upload": fields.Raw,
"system_parameters": fields.Nested(system_parameters_fields),
}

@marshal_with(parameters_fields)
@marshal_with(fields.parameters_fields)
def get(self, app_model: App, end_user): def get(self, app_model: App, end_user):
"""Retrieve app parameters.""" """Retrieve app parameters."""
if app_model.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}: if app_model.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}:
user_input_form = workflow.user_input_form(to_old_structure=True) user_input_form = workflow.user_input_form(to_old_structure=True)
else: else:
app_model_config = app_model.app_model_config app_model_config = app_model.app_model_config
if app_model_config is None:
raise AppUnavailableError()

features_dict = app_model_config.to_dict() features_dict = app_model_config.to_dict()


user_input_form = features_dict.get("user_input_form", []) user_input_form = features_dict.get("user_input_form", [])


return {
"opening_statement": features_dict.get("opening_statement"),
"suggested_questions": features_dict.get("suggested_questions", []),
"suggested_questions_after_answer": features_dict.get(
"suggested_questions_after_answer", {"enabled": False}
),
"speech_to_text": features_dict.get("speech_to_text", {"enabled": False}),
"text_to_speech": features_dict.get("text_to_speech", {"enabled": False}),
"retriever_resource": features_dict.get("retriever_resource", {"enabled": False}),
"annotation_reply": features_dict.get("annotation_reply", {"enabled": False}),
"more_like_this": features_dict.get("more_like_this", {"enabled": False}),
"user_input_form": user_input_form,
"sensitive_word_avoidance": features_dict.get(
"sensitive_word_avoidance", {"enabled": False, "type": "", "configs": []}
),
"file_upload": features_dict.get(
"file_upload",
{
"image": {
"enabled": False,
"number_limits": 3,
"detail": "high",
"transfer_methods": ["remote_url", "local_file"],
}
},
),
"system_parameters": {
"image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
"video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
"audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
"file_size_limit": dify_config.UPLOAD_FILE_SIZE_LIMIT,
},
}
return controller_helpers.get_parameters_from_feature_dict(
features_dict=features_dict, user_input_form=user_input_form
)




class AppMeta(WebApiResource): class AppMeta(WebApiResource):

+ 2
- 3
api/core/app/app_config/features/file_upload/manager.py Voir le fichier

from collections.abc import Mapping from collections.abc import Mapping
from typing import Any from typing import Any


from core.file.models import FileExtraConfig
from models import FileUploadConfig
from core.file import FileExtraConfig




class FileUploadConfigManager: class FileUploadConfigManager:
if not config.get("file_upload"): if not config.get("file_upload"):
config["file_upload"] = {} config["file_upload"] = {}
else: else:
FileUploadConfig.model_validate(config["file_upload"])
FileExtraConfig.model_validate(config["file_upload"])


return config, ["file_upload"] return config, ["file_upload"]

+ 1
- 0
api/fields/file_fields.py Voir le fichier

"image_file_size_limit": fields.Integer, "image_file_size_limit": fields.Integer,
"video_file_size_limit": fields.Integer, "video_file_size_limit": fields.Integer,
"audio_file_size_limit": fields.Integer, "audio_file_size_limit": fields.Integer,
"workflow_file_upload_limit": fields.Integer,
} }


file_fields = { file_fields = {

+ 0
- 2
api/models/__init__.py Voir le fichier

AppMode, AppMode,
Conversation, Conversation,
EndUser, EndUser,
FileUploadConfig,
InstalledApp, InstalledApp,
Message, Message,
MessageAnnotation, MessageAnnotation,
"Tenant", "Tenant",
"Conversation", "Conversation",
"MessageAnnotation", "MessageAnnotation",
"FileUploadConfig",
"ToolFile", "ToolFile",
] ]

+ 2
- 11
api/models/model.py Voir le fichier

import json import json
import re import re
import uuid import uuid
from collections.abc import Mapping, Sequence
from collections.abc import Mapping
from datetime import datetime from datetime import datetime
from enum import Enum from enum import Enum
from typing import Any, Literal, Optional from typing import Any, Literal, Optional
import sqlalchemy as sa import sqlalchemy as sa
from flask import request from flask import request
from flask_login import UserMixin from flask_login import UserMixin
from pydantic import BaseModel, Field
from sqlalchemy import Float, func, text from sqlalchemy import Float, func, text
from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.orm import Mapped, mapped_column


from .types import StringUUID from .types import StringUUID




class FileUploadConfig(BaseModel):
enabled: bool = Field(default=False)
allowed_file_types: Sequence[FileType] = Field(default_factory=list)
allowed_extensions: Sequence[str] = Field(default_factory=list)
allowed_upload_methods: Sequence[FileTransferMethod] = Field(default_factory=list)
number_limits: int = Field(default=0, gt=0, le=10)


class DifySetup(db.Model): class DifySetup(db.Model):
__tablename__ = "dify_setups" __tablename__ = "dify_setups"
__table_args__ = (db.PrimaryKeyConstraint("version", name="dify_setup_pkey"),) __table_args__ = (db.PrimaryKeyConstraint("version", name="dify_setup_pkey"),)
return site return site


@property @property
def app_model_config(self) -> Optional["AppModelConfig"]:
def app_model_config(self):
if self.app_model_config_id: if self.app_model_config_id:
return db.session.query(AppModelConfig).filter(AppModelConfig.id == self.app_model_config_id).first() return db.session.query(AppModelConfig).filter(AppModelConfig.id == self.app_model_config_id).first()



+ 1
- 0
docker/.env.example Voir le fichier

WORKFLOW_MAX_EXECUTION_TIME=1200 WORKFLOW_MAX_EXECUTION_TIME=1200
WORKFLOW_CALL_MAX_DEPTH=5 WORKFLOW_CALL_MAX_DEPTH=5
MAX_VARIABLE_SIZE=204800 MAX_VARIABLE_SIZE=204800
WORKFLOW_FILE_UPLOAD_LIMIT=10


# HTTP request node in workflow configuration # HTTP request node in workflow configuration
HTTP_REQUEST_NODE_MAX_BINARY_SIZE=10485760 HTTP_REQUEST_NODE_MAX_BINARY_SIZE=10485760

+ 1
- 0
docker/docker-compose.yaml Voir le fichier

x-shared-env: &shared-api-worker-env x-shared-env: &shared-api-worker-env
WORKFLOW_FILE_UPLOAD_LIMIT: ${WORKFLOW_FILE_UPLOAD_LIMIT:-10}
LOG_LEVEL: ${LOG_LEVEL:-INFO} LOG_LEVEL: ${LOG_LEVEL:-INFO}
LOG_FILE: ${LOG_FILE:-} LOG_FILE: ${LOG_FILE:-}
LOG_FILE_MAX_SIZE: ${LOG_FILE_MAX_SIZE:-20} LOG_FILE_MAX_SIZE: ${LOG_FILE_MAX_SIZE:-20}

+ 1
- 0
web/app/components/base/file-uploader/constants.ts Voir le fichier

export const FILE_SIZE_LIMIT = 15 * 1024 * 1024 export const FILE_SIZE_LIMIT = 15 * 1024 * 1024
export const AUDIO_SIZE_LIMIT = 50 * 1024 * 1024 export const AUDIO_SIZE_LIMIT = 50 * 1024 * 1024
export const VIDEO_SIZE_LIMIT = 100 * 1024 * 1024 export const VIDEO_SIZE_LIMIT = 100 * 1024 * 1024
export const MAX_FILE_UPLOAD_LIMIT = 10


export const FILE_URL_REGEX = /^(https?|ftp):\/\// export const FILE_URL_REGEX = /^(https?|ftp):\/\//

+ 3
- 0
web/app/components/base/file-uploader/hooks.ts Voir le fichier

AUDIO_SIZE_LIMIT, AUDIO_SIZE_LIMIT,
FILE_SIZE_LIMIT, FILE_SIZE_LIMIT,
IMG_SIZE_LIMIT, IMG_SIZE_LIMIT,
MAX_FILE_UPLOAD_LIMIT,
VIDEO_SIZE_LIMIT, VIDEO_SIZE_LIMIT,
} from '@/app/components/base/file-uploader/constants' } from '@/app/components/base/file-uploader/constants'
import { useToastContext } from '@/app/components/base/toast' import { useToastContext } from '@/app/components/base/toast'
const docSizeLimit = Number(fileUploadConfig?.file_size_limit) * 1024 * 1024 || FILE_SIZE_LIMIT const docSizeLimit = Number(fileUploadConfig?.file_size_limit) * 1024 * 1024 || FILE_SIZE_LIMIT
const audioSizeLimit = Number(fileUploadConfig?.audio_file_size_limit) * 1024 * 1024 || AUDIO_SIZE_LIMIT const audioSizeLimit = Number(fileUploadConfig?.audio_file_size_limit) * 1024 * 1024 || AUDIO_SIZE_LIMIT
const videoSizeLimit = Number(fileUploadConfig?.video_file_size_limit) * 1024 * 1024 || VIDEO_SIZE_LIMIT const videoSizeLimit = Number(fileUploadConfig?.video_file_size_limit) * 1024 * 1024 || VIDEO_SIZE_LIMIT
const maxFileUploadLimit = Number(fileUploadConfig?.workflow_file_upload_limit) || MAX_FILE_UPLOAD_LIMIT


return { return {
imgSizeLimit, imgSizeLimit,
docSizeLimit, docSizeLimit,
audioSizeLimit, audioSizeLimit,
videoSizeLimit, videoSizeLimit,
maxFileUploadLimit,
} }
} }



+ 8
- 2
web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx Voir le fichier

allowed_file_extensions, allowed_file_extensions,
} = payload } = payload
const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig) const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit(fileUploadConfigResponse)
const {
imgSizeLimit,
docSizeLimit,
audioSizeLimit,
videoSizeLimit,
maxFileUploadLimit,
} = useFileSizeLimit(fileUploadConfigResponse)


const handleSupportFileTypeChange = useCallback((type: SupportUploadFileTypes) => { const handleSupportFileTypeChange = useCallback((type: SupportUploadFileTypes) => {
const newPayload = produce(payload, (draft) => { const newPayload = produce(payload, (draft) => {
<InputNumberWithSlider <InputNumberWithSlider
value={max_length} value={max_length}
min={1} min={1}
max={10}
max={maxFileUploadLimit}
onChange={handleMaxUploadNumLimitChange} onChange={handleMaxUploadNumLimitChange}
/> />
</div> </div>

+ 1
- 1
web/models/common.ts Voir le fichier

file_size_limit: number // default is 15MB file_size_limit: number // default is 15MB
audio_file_size_limit?: number // default is 50MB audio_file_size_limit?: number // default is 50MB
video_file_size_limit?: number // default is 100MB video_file_size_limit?: number // default is 100MB
workflow_file_upload_limit?: number // default is 10
} }


export type InvitationResult = { export type InvitationResult = {

Chargement…
Annuler
Enregistrer