From e32116b9a3d3dfa1fd9c9d0b5650fc41eb89f116 Mon Sep 17 00:00:00 2001 From: KVOJJJin Date: Wed, 23 Oct 2024 17:03:44 +0800 Subject: [PATCH] Feat: use file size limit from api (#9711) --- .../base/file-uploader/constants.ts | 4 + .../components/base/file-uploader/hooks.ts | 116 ++++++++++++++++-- .../_base/components/file-upload-setting.tsx | 10 +- web/i18n/en-US/app-debug.ts | 2 +- web/i18n/en-US/common.ts | 2 +- web/i18n/zh-Hans/app-debug.ts | 2 +- web/i18n/zh-Hans/common.ts | 2 +- web/models/common.ts | 6 +- 8 files changed, 127 insertions(+), 17 deletions(-) diff --git a/web/app/components/base/file-uploader/constants.ts b/web/app/components/base/file-uploader/constants.ts index e6cc2995f9..629fe2566b 100644 --- a/web/app/components/base/file-uploader/constants.ts +++ b/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):\/\// diff --git a/web/app/components/base/file-uploader/hooks.ts b/web/app/components/base/file-uploader/hooks.ts index 5e126a87b5..ed299eca3e 100644 --- a/web/app/components/base/file-uploader/hooks.ts +++ b/web/app/components/base/file-uploader/hooks.ts @@ -3,6 +3,7 @@ import { useCallback, useState, } from 'react' +import useSWR from 'swr' import { useParams } from 'next/navigation' import produce from 'immer' import { v4 as uuid4 } from 'uuid' @@ -14,19 +15,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 { fetchFileUploadConfig, fetchRemoteFileInfo } from '@/service/common' + +export const useFileSizeLimit = () => { + const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig) + const imgSizeLimit = Number(fileUploadConfigResponse?.image_file_size_limit) * 1024 * 1024 || IMG_SIZE_LIMIT + const docSizeLimit = Number(fileUploadConfigResponse?.file_size_limit) * 1024 * 1024 || FILE_SIZE_LIMIT + const audioSizeLimit = Number(fileUploadConfigResponse?.audio_file_size_limit) * 1024 * 1024 || AUDIO_SIZE_LIMIT + const videoSizeLimit = Number(fileUploadConfigResponse?.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() + + 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 +212,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 +238,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 +285,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) => { const file = e.clipboardData?.files[0] diff --git a/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx b/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx index 77ff2fd5c1..72df3b20d2 100644 --- a/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx +++ b/web/app/components/workflow/nodes/_base/components/file-upload-setting.tsx @@ -10,7 +10,7 @@ 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 { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks' import { formatFileSize } from '@/utils/format' type Props = { @@ -36,6 +36,7 @@ const FileUploadSetting: FC = ({ allowed_file_types, allowed_file_extensions, } = payload + const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit() const handleSupportFileTypeChange = useCallback((type: SupportUploadFileTypes) => { const newPayload = produce(payload, (draft) => { @@ -142,7 +143,12 @@ const FileUploadSetting: FC = ({ title={t('appDebug.variableConfig.maxNumberOfUploads')!} >
-
{t('appDebug.variableConfig.maxNumberTip', { size: formatFileSize(FILE_SIZE_LIMIT) })}
+
{t('appDebug.variableConfig.maxNumberTip', { + imgLimit: formatFileSize(imgSizeLimit), + docLimit: formatFileSize(docSizeLimit), + audioLimit: formatFileSize(audioSizeLimit), + videoLimit: formatFileSize(videoSizeLimit), + })}