Browse Source

Feat: use file size limit from api (#9739)

KVOJJJin 5 months ago
parent
commit
5d1424f67c

+ 1 - 4
web/app/components/app/configuration/debug/index.tsx

@@ -1,6 +1,5 @@
 'use client'
 import type { FC } from 'react'
-import useSWR from 'swr'
 import { useTranslation } from 'react-i18next'
 import React, { useCallback, useEffect, useRef, useState } from 'react'
 import produce, { setAutoFreeze } from 'immer'
@@ -39,7 +38,6 @@ import { promptVariablesToUserInputsForm } from '@/utils/model-config'
 import TextGeneration from '@/app/components/app/text-generate/item'
 import { IS_CE_EDITION } from '@/config'
 import type { Inputs } from '@/models/debug'
-import { fetchFileUploadConfig } from '@/service/common'
 import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
 import { ModelFeatureEnum, ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
 import type { ModelParameterModalProps } from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
@@ -94,7 +92,6 @@ const Debug: FC<IDebug> = ({
   } = useContext(ConfigContext)
   const { eventEmitter } = useEventEmitterContextContext()
   const { data: text2speechDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding)
-  const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
   useEffect(() => {
     setAutoFreeze(false)
     return () => {
@@ -452,7 +449,7 @@ const Debug: FC<IDebug> = ({
             visionConfig={{
               ...features.file! as VisionSettings,
               transfer_methods: features.file!.allowed_file_upload_methods || [],
-              image_file_size_limit: fileUploadConfigResponse?.image_file_size_limit,
+              image_file_size_limit: features.file?.fileUploadConfig?.image_file_size_limit,
             }}
             onVisionFilesChange={setCompletionFiles}
           />

+ 10 - 2
web/app/components/app/configuration/index.tsx

@@ -1,6 +1,7 @@
 'use client'
 import type { FC } from 'react'
 import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import useSWR from 'swr'
 import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
 import { usePathname } from 'next/navigation'
@@ -69,6 +70,7 @@ import type { Features as FeaturesData, FileUpload } from '@/app/components/base
 import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
 import { SupportUploadFileTypes } from '@/app/components/workflow/types'
 import NewFeaturePanel from '@/app/components/base/features/new-feature-panel'
+import { fetchFileUploadConfig } from '@/service/common'
 
 type PublishConfig = {
   modelConfig: ModelConfig
@@ -84,6 +86,8 @@ const Configuration: FC = () => {
     showAppConfigureFeaturesModal: state.showAppConfigureFeaturesModal,
     setShowAppConfigureFeaturesModal: state.setShowAppConfigureFeaturesModal,
   })))
+  const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
+
   const latestPublishedAt = useMemo(() => appDetail?.model_config.updated_at, [appDetail])
   const [formattingChanged, setFormattingChanged] = useState(false)
   const { setShowAccountSettingModal } = useModalContext()
@@ -462,12 +466,13 @@ const Configuration: FC = () => {
         allowed_file_extensions: modelConfig.file_upload?.allowed_file_extensions || FILE_EXTS[SupportUploadFileTypes.image].map(ext => `.${ext}`),
         allowed_file_upload_methods: modelConfig.file_upload?.allowed_file_upload_methods || modelConfig.file_upload?.image?.transfer_methods || ['local_file', 'remote_url'],
         number_limits: modelConfig.file_upload?.number_limits || modelConfig.file_upload?.image?.number_limits || 3,
+        fileUploadConfig: fileUploadConfigResponse,
       } as FileUpload,
       suggested: modelConfig.suggested_questions_after_answer || { enabled: false },
       citation: modelConfig.retriever_resource || { enabled: false },
       annotationReply: modelConfig.annotation_reply || { enabled: false },
     }
-  }, [modelConfig])
+  }, [fileUploadConfigResponse, modelConfig])
   const handleFeaturesChange = useCallback((flag: any) => {
     setShowAppConfigureFeaturesModal(true)
     if (flag)
@@ -684,6 +689,9 @@ const Configuration: FC = () => {
       },
     }))
 
+    const fileUpload = { ...features?.file }
+    delete fileUpload?.fileUploadConfig
+
     // new model config data struct
     const data: BackendModelConfig = {
       // Simple Mode prompt
@@ -700,7 +708,7 @@ const Configuration: FC = () => {
       sensitive_word_avoidance: features?.moderation as any,
       speech_to_text: features?.speech2text as any,
       text_to_speech: features?.text2speech as any,
-      file_upload: features?.file as any,
+      file_upload: fileUpload as any,
       suggested_questions_after_answer: features?.suggested as any,
       retriever_resource: features?.citation as any,
       agent_mode: {

+ 4 - 0
web/app/components/base/chat/chat-with-history/chat-wrapper.tsx

@@ -40,6 +40,10 @@ const ChatWrapper = () => {
 
     return {
       ...config,
+      file_upload: {
+        ...(config as any).file_upload,
+        fileUploadConfig: (config as any).system_parameters,
+      },
       supportFeedback: true,
       opening_statement: currentConversationId ? currentConversationItem?.introduction : (config as any).opening_statement,
     } as ChatConfig

+ 3 - 0
web/app/components/base/chat/chat-with-history/config-panel/form.tsx

@@ -9,6 +9,7 @@ import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uplo
 const Form = () => {
   const { t } = useTranslation()
   const {
+    appParams,
     inputsForms,
     newConversationInputs,
     newConversationInputsRef,
@@ -61,6 +62,7 @@ const Form = () => {
             allowed_file_extensions: form.allowed_file_extensions,
             allowed_file_upload_methods: form.allowed_file_upload_methods,
             number_limits: 1,
+            fileUploadConfig: (appParams as any).system_parameters,
           }}
         />
       )
@@ -75,6 +77,7 @@ const Form = () => {
             allowed_file_extensions: form.allowed_file_extensions,
             allowed_file_upload_methods: form.allowed_file_upload_methods,
             number_limits: form.max_length,
+            fileUploadConfig: (appParams as any).system_parameters,
           }}
         />
       )

+ 4 - 0
web/app/components/base/chat/embedded-chatbot/chat-wrapper.tsx

@@ -42,6 +42,10 @@ const ChatWrapper = () => {
 
     return {
       ...config,
+      file_upload: {
+        ...(config as any).file_upload,
+        fileUploadConfig: (config as any).system_parameters,
+      },
       supportFeedback: true,
       opening_statement: currentConversationId ? currentConversationItem?.introduction : (config as any).opening_statement,
     } as ChatConfig

+ 3 - 0
web/app/components/base/chat/embedded-chatbot/config-panel/form.tsx

@@ -9,6 +9,7 @@ import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uplo
 const Form = () => {
   const { t } = useTranslation()
   const {
+    appParams,
     inputsForms,
     newConversationInputs,
     newConversationInputsRef,
@@ -73,6 +74,7 @@ const Form = () => {
             allowed_file_extensions: form.allowed_file_extensions,
             allowed_file_upload_methods: form.allowed_file_upload_methods,
             number_limits: 1,
+            fileUploadConfig: (appParams as any).system_parameters,
           }}
         />
       )
@@ -87,6 +89,7 @@ const Form = () => {
             allowed_file_extensions: form.allowed_file_extensions,
             allowed_file_upload_methods: form.allowed_file_upload_methods,
             number_limits: form.max_length,
+            fileUploadConfig: (appParams as any).system_parameters,
           }}
         />
       )

+ 2 - 0
web/app/components/base/features/types.ts

@@ -1,4 +1,5 @@
 import type { Resolution, TransferMethod, TtsAutoPlay } from '@/types/app'
+import type { FileUploadConfigResponse } from '@/models/common'
 
 export type EnabledOrDisabled = {
   enabled?: boolean
@@ -38,6 +39,7 @@ export type FileUpload = {
   allowed_file_extensions?: string[]
   allowed_file_upload_methods?: TransferMethod[]
   number_limits?: number
+  fileUploadConfig?: FileUploadConfigResponse
 } & EnabledOrDisabled
 
 export type AnnotationReplyConfig = {

+ 4 - 0
web/app/components/base/file-uploader/constants.ts

@@ -1,3 +1,7 @@
+// fallback for file size limit of dify_config
+export const IMG_SIZE_LIMIT = 10 * 1024 * 1024
 export const FILE_SIZE_LIMIT = 15 * 1024 * 1024
+export const AUDIO_SIZE_LIMIT = 50 * 1024 * 1024
+export const VIDEO_SIZE_LIMIT = 100 * 1024 * 1024
 
 export const FILE_URL_REGEX = /^(https?|ftp):\/\//

+ 105 - 8
web/app/components/base/file-uploader/hooks.ts

@@ -14,19 +14,113 @@ import {
   getSupportFileType,
   isAllowedFileExtension,
 } from './utils'
-import { FILE_SIZE_LIMIT } from './constants'
+import {
+  AUDIO_SIZE_LIMIT,
+  FILE_SIZE_LIMIT,
+  IMG_SIZE_LIMIT,
+  VIDEO_SIZE_LIMIT,
+} from '@/app/components/base/file-uploader/constants'
 import { useToastContext } from '@/app/components/base/toast'
 import { TransferMethod } from '@/types/app'
 import { SupportUploadFileTypes } from '@/app/components/workflow/types'
 import type { FileUpload } from '@/app/components/base/features/types'
 import { formatFileSize } from '@/utils/format'
 import { fetchRemoteFileInfo } from '@/service/common'
+import type { FileUploadConfigResponse } from '@/models/common'
+
+export const useFileSizeLimit = (fileUploadConfig?: FileUploadConfigResponse) => {
+  const imgSizeLimit = Number(fileUploadConfig?.image_file_size_limit) * 1024 * 1024 || IMG_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 videoSizeLimit = Number(fileUploadConfig?.video_file_size_limit) * 1024 * 1024 || VIDEO_SIZE_LIMIT
+
+  return {
+    imgSizeLimit,
+    docSizeLimit,
+    audioSizeLimit,
+    videoSizeLimit,
+  }
+}
 
 export const useFile = (fileConfig: FileUpload) => {
   const { t } = useTranslation()
   const { notify } = useToastContext()
   const fileStore = useFileStore()
   const params = useParams()
+  const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit(fileConfig.fileUploadConfig)
+
+  const checkSizeLimit = (fileType: string, fileSize: number) => {
+    switch (fileType) {
+      case SupportUploadFileTypes.image: {
+        if (fileSize > imgSizeLimit) {
+          notify({
+            type: 'error',
+            message: t('common.fileUploader.uploadFromComputerLimit', {
+              type: SupportUploadFileTypes.image,
+              size: formatFileSize(imgSizeLimit),
+            }),
+          })
+          return false
+        }
+        return true
+      }
+      case SupportUploadFileTypes.document: {
+        if (fileSize > docSizeLimit) {
+          notify({
+            type: 'error',
+            message: t('common.fileUploader.uploadFromComputerLimit', {
+              type: SupportUploadFileTypes.document,
+              size: formatFileSize(docSizeLimit),
+            }),
+          })
+          return false
+        }
+        return true
+      }
+      case SupportUploadFileTypes.audio: {
+        if (fileSize > audioSizeLimit) {
+          notify({
+            type: 'error',
+            message: t('common.fileUploader.uploadFromComputerLimit', {
+              type: SupportUploadFileTypes.audio,
+              size: formatFileSize(audioSizeLimit),
+            }),
+          })
+          return false
+        }
+        return true
+      }
+      case SupportUploadFileTypes.video: {
+        if (fileSize > videoSizeLimit) {
+          notify({
+            type: 'error',
+            message: t('common.fileUploader.uploadFromComputerLimit', {
+              type: SupportUploadFileTypes.video,
+              size: formatFileSize(videoSizeLimit),
+            }),
+          })
+          return false
+        }
+        return true
+      }
+      case SupportUploadFileTypes.custom: {
+        if (fileSize > docSizeLimit) {
+          notify({
+            type: 'error',
+            message: t('common.fileUploader.uploadFromComputerLimit', {
+              type: SupportUploadFileTypes.document,
+              size: formatFileSize(docSizeLimit),
+            }),
+          })
+          return false
+        }
+        return true
+      }
+      default: {
+        return true
+      }
+    }
+  }
 
   const handleAddFile = useCallback((newFile: FileEntity) => {
     const {
@@ -117,12 +211,15 @@ export const useFile = (fileConfig: FileUpload) => {
         progress: 100,
         supportFileType: getSupportFileType(url, res.file_type, allowedFileTypes?.includes(SupportUploadFileTypes.custom)),
       }
-      handleUpdateFile(newFile)
+      if (!checkSizeLimit(newFile.supportFileType, newFile.size))
+        handleRemoveFile(uploadingFile.id)
+      else
+        handleUpdateFile(newFile)
     }).catch(() => {
       notify({ type: 'error', message: t('common.fileUploader.pasteFileLinkInvalid') })
       handleRemoveFile(uploadingFile.id)
     })
-  }, [handleAddFile, handleUpdateFile, notify, t, handleRemoveFile, fileConfig?.allowed_file_types])
+  }, [checkSizeLimit, handleAddFile, handleUpdateFile, notify, t, handleRemoveFile, fileConfig?.allowed_file_types])
 
   const handleLoadFileFromLinkSuccess = useCallback(() => { }, [])
 
@@ -140,13 +237,13 @@ export const useFile = (fileConfig: FileUpload) => {
       notify({ type: 'error', message: t('common.fileUploader.fileExtensionNotSupport') })
       return
     }
-    if (file.size > FILE_SIZE_LIMIT) {
-      notify({ type: 'error', message: t('common.fileUploader.uploadFromComputerLimit', { size: formatFileSize(FILE_SIZE_LIMIT) }) })
+    const allowedFileTypes = fileConfig.allowed_file_types
+    const fileType = getSupportFileType(file.name, file.type, allowedFileTypes?.includes(SupportUploadFileTypes.custom))
+    if (!checkSizeLimit(fileType, file.size))
       return
-    }
+
     const reader = new FileReader()
     const isImage = file.type.startsWith('image')
-    const allowedFileTypes = fileConfig.allowed_file_types
 
     reader.addEventListener(
       'load',
@@ -187,7 +284,7 @@ export const useFile = (fileConfig: FileUpload) => {
       false,
     )
     reader.readAsDataURL(file)
-  }, [notify, t, handleAddFile, handleUpdateFile, params.token, fileConfig?.allowed_file_types, fileConfig?.allowed_file_extensions])
+  }, [checkSizeLimit, notify, t, handleAddFile, handleUpdateFile, params.token, fileConfig?.allowed_file_types, fileConfig?.allowed_file_extensions])
 
   const handleClipboardPasteFile = useCallback((e: ClipboardEvent<HTMLTextAreaElement>) => {
     const file = e.clipboardData?.files[0]

+ 1 - 0
web/app/components/share/text-generation/index.tsx

@@ -390,6 +390,7 @@ const TextGeneration: FC<IMainProps> = ({
       setVisionConfig({
         ...file_upload.image,
         image_file_size_limit: appParams?.system_parameters?.image_file_size_limit,
+        fileUploadConfig: appParams?.system_parameters,
       })
       const prompt_variables = userInputsFormToPromptVariables(user_input_form)
       setPromptConfig({

+ 8 - 2
web/app/components/share/text-generation/run-once/index.tsx

@@ -96,13 +96,19 @@ const RunOnce: FC<IRunOnceProps> = ({
                 {item.type === 'file' && (
                   <FileUploaderInAttachmentWrapper
                     onChange={(files) => { onInputsChange({ ...inputs, [item.key]: getProcessedFiles(files)[0] }) }}
-                    fileConfig={item.config as any}
+                    fileConfig={{
+                      ...item.config,
+                      fileUploadConfig: (visionConfig as any).fileUploadConfig,
+                    }}
                   />
                 )}
                 {item.type === 'file-list' && (
                   <FileUploaderInAttachmentWrapper
                     onChange={(files) => { onInputsChange({ ...inputs, [item.key]: getProcessedFiles(files) }) }}
-                    fileConfig={item.config as any}
+                    fileConfig={{
+                      ...item.config,
+                      fileUploadConfig: (visionConfig as any).fileUploadConfig,
+                    }}
                   />
                 )}
               </div>

+ 4 - 0
web/app/components/workflow/index.tsx

@@ -9,6 +9,7 @@ import {
   useRef,
   useState,
 } from 'react'
+import useSWR from 'swr'
 import { setAutoFreeze } from 'immer'
 import {
   useEventListener,
@@ -93,6 +94,7 @@ import { useFeaturesStore } from '@/app/components/base/features/hooks'
 import { useEventEmitterContextContext } from '@/context/event-emitter'
 import Confirm from '@/app/components/base/confirm'
 import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
+import { fetchFileUploadConfig } from '@/service/common'
 
 const nodeTypes = {
   [CUSTOM_NODE]: CustomNode,
@@ -382,6 +384,7 @@ const WorkflowWrap = memo(() => {
     data,
     isLoading,
   } = useWorkflowInit()
+  const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
 
   const nodesData = useMemo(() => {
     if (data)
@@ -417,6 +420,7 @@ const WorkflowWrap = memo(() => {
       allowed_file_extensions: features.file_upload?.allowed_file_extensions || FILE_EXTS[SupportUploadFileTypes.image].map(ext => `.${ext}`),
       allowed_file_upload_methods: features.file_upload?.allowed_file_upload_methods || features.file_upload?.image?.transfer_methods || ['local_file', 'remote_url'],
       number_limits: features.file_upload?.number_limits || features.file_upload?.image?.number_limits || 3,
+      fileUploadConfig: fileUploadConfigResponse,
     },
     opening: {
       enabled: !!features.opening_statement,

+ 35 - 4
web/app/components/workflow/nodes/_base/components/before-run-form/form-item.tsx

@@ -22,6 +22,7 @@ import { VarBlockIcon } from '@/app/components/workflow/block-icon'
 import { Line3 } from '@/app/components/base/icons/src/public/common'
 import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
 import { BubbleX } from '@/app/components/base/icons/src/vender/line/others'
+import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
 import cn from '@/utils/classnames'
 
 type Props = {
@@ -168,10 +169,25 @@ const FormItem: FC<Props> = ({
                 onChange(null)
             }}
             fileConfig={{
-              allowed_file_types: inStepRun ? [SupportUploadFileTypes.custom] : payload.allowed_file_types,
-              allowed_file_extensions: inStepRun ? [] : payload.allowed_file_extensions,
+              allowed_file_types: inStepRun
+                ? [
+                  SupportUploadFileTypes.image,
+                  SupportUploadFileTypes.document,
+                  SupportUploadFileTypes.audio,
+                  SupportUploadFileTypes.video,
+                ]
+                : payload.allowed_file_types,
+              allowed_file_extensions: inStepRun
+                ? [
+                  ...FILE_EXTS[SupportUploadFileTypes.image],
+                  ...FILE_EXTS[SupportUploadFileTypes.document],
+                  ...FILE_EXTS[SupportUploadFileTypes.audio],
+                  ...FILE_EXTS[SupportUploadFileTypes.video],
+                ]
+                : payload.allowed_file_extensions,
               allowed_file_upload_methods: inStepRun ? [TransferMethod.local_file, TransferMethod.remote_url] : payload.allowed_file_upload_methods,
               number_limits: 1,
+              fileUploadConfig: fileSettings?.fileUploadConfig,
             }}
           />
         )}
@@ -180,10 +196,25 @@ const FormItem: FC<Props> = ({
             value={value}
             onChange={files => onChange(files)}
             fileConfig={{
-              allowed_file_types: inStepRun ? [SupportUploadFileTypes.custom] : payload.allowed_file_types,
-              allowed_file_extensions: inStepRun ? [] : payload.allowed_file_extensions,
+              allowed_file_types: inStepRun
+                ? [
+                  SupportUploadFileTypes.image,
+                  SupportUploadFileTypes.document,
+                  SupportUploadFileTypes.audio,
+                  SupportUploadFileTypes.video,
+                ]
+                : payload.allowed_file_types,
+              allowed_file_extensions: inStepRun
+                ? [
+                  ...FILE_EXTS[SupportUploadFileTypes.image],
+                  ...FILE_EXTS[SupportUploadFileTypes.document],
+                  ...FILE_EXTS[SupportUploadFileTypes.audio],
+                  ...FILE_EXTS[SupportUploadFileTypes.video],
+                ]
+                : payload.allowed_file_extensions,
               allowed_file_upload_methods: inStepRun ? [TransferMethod.local_file, TransferMethod.remote_url] : payload.allowed_file_upload_methods,
               number_limits: inStepRun ? 5 : payload.max_length,
+              fileUploadConfig: fileSettings?.fileUploadConfig,
             }}
           />
         )}

+ 12 - 2
web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx

@@ -1,6 +1,7 @@
 'use client'
 import type { FC } from 'react'
 import React, { useCallback } from 'react'
+import useSWR from 'swr'
 import produce from 'immer'
 import { useTranslation } from 'react-i18next'
 import type { UploadFileSetting } from '../../../types'
@@ -10,7 +11,8 @@ import FileTypeItem from './file-type-item'
 import InputNumberWithSlider from './input-number-with-slider'
 import Field from '@/app/components/app/configuration/config-var/config-modal/field'
 import { TransferMethod } from '@/types/app'
-import { FILE_SIZE_LIMIT } from '@/app/components/base/file-uploader/constants'
+import { fetchFileUploadConfig } from '@/service/common'
+import { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks'
 import { formatFileSize } from '@/utils/format'
 
 type Props = {
@@ -36,6 +38,8 @@ const FileUploadSetting: FC<Props> = ({
     allowed_file_types,
     allowed_file_extensions,
   } = payload
+  const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
+  const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit(fileUploadConfigResponse)
 
   const handleSupportFileTypeChange = useCallback((type: SupportUploadFileTypes) => {
     const newPayload = produce(payload, (draft) => {
@@ -142,7 +146,13 @@ const FileUploadSetting: FC<Props> = ({
           title={t('appDebug.variableConfig.maxNumberOfUploads')!}
         >
           <div>
-            <div className='mb-1.5 text-text-tertiary body-xs-regular'>{t('appDebug.variableConfig.maxNumberTip', { size: formatFileSize(FILE_SIZE_LIMIT) })}</div>
+            <div className='mb-1.5 text-text-tertiary body-xs-regular'>{t('appDebug.variableConfig.maxNumberTip', {
+              imgLimit: formatFileSize(imgSizeLimit),
+              docLimit: formatFileSize(docSizeLimit),
+              audioLimit: formatFileSize(audioSizeLimit),
+              videoLimit: formatFileSize(videoSizeLimit),
+            })}</div>
+
             <InputNumberWithSlider
               value={max_length}
               min={1}

+ 1 - 1
web/i18n/en-US/app-debug.ts

@@ -386,7 +386,7 @@ const translation = {
     'localUpload': 'Local Upload',
     'both': 'Both',
     'maxNumberOfUploads': 'Max number of uploads',
-    'maxNumberTip': 'Max {{size}} each',
+    'maxNumberTip': 'Document < {{docLimit}}, image < {{imgLimit}}, audio < {{audioLimit}}, video < {{videoLimit}}',
     'errorMsg': {
       labelNameRequired: 'Label name is required',
       varNameCanBeRepeat: 'Variable name can not be repeated',

+ 1 - 1
web/i18n/en-US/common.ts

@@ -572,7 +572,7 @@ const translation = {
     pasteFileLinkInputPlaceholder: 'Enter URL...',
     uploadFromComputerReadError: 'File reading failed, please try again.',
     uploadFromComputerUploadError: 'File upload failed, please upload again.',
-    uploadFromComputerLimit: 'Upload File cannot exceed {{size}}',
+    uploadFromComputerLimit: 'Upload {{type}} cannot exceed {{size}}',
     pasteFileLinkInvalid: 'Invalid file link',
     fileExtensionNotSupport: 'File extension not supported',
   },

+ 1 - 1
web/i18n/zh-Hans/app-debug.ts

@@ -379,7 +379,7 @@ const translation = {
     'localUpload': '本地上传',
     'both': '两者',
     'maxNumberOfUploads': '最大上传数',
-    'maxNumberTip': '最大上传文件大小为 {{size}}',
+    'maxNumberTip': '文档 < {{docLimit}}, 图片 < {{imgLimit}}, 音频 < {{audioLimit}}, 视频 < {{videoLimit}}',
     'content': '内容',
     'errorMsg': {
       labelNameRequired: '显示名称必填',

+ 1 - 1
web/i18n/zh-Hans/common.ts

@@ -572,7 +572,7 @@ const translation = {
     pasteFileLinkInputPlaceholder: '输入文件链接',
     uploadFromComputerReadError: '文件读取失败,请重新选择。',
     uploadFromComputerUploadError: '文件上传失败,请重新上传。',
-    uploadFromComputerLimit: '上传文件不能超过 {{size}}',
+    uploadFromComputerLimit: '上传 {{type}} 不能超过 {{size}}',
     pasteFileLinkInvalid: '文件链接无效',
     fileExtensionNotSupport: '文件类型不支持',
   },

+ 5 - 2
web/models/common.ts

@@ -211,9 +211,12 @@ export type PluginProvider = {
 }
 
 export type FileUploadConfigResponse = {
-  file_size_limit: number
   batch_count_limit: number
-  image_file_size_limit?: number | string
+  image_file_size_limit?: number | string // default is 10MB
+  file_size_limit: number // default is 15MB
+  audio_file_size_limit?: number // default is 50MB
+  video_file_size_limit?: number // default is 100MB
+
 }
 
 export type InvitationResult = {