import mime from 'mime' import { FileAppearanceTypeEnum, SupportUploadFileTypes } from './types' import type { FileEntity, FileResponse } from './types' import { FILE_EXTS } from './constants' import { upload } from '@/service/base' import { TransferMethod } from '@/types/app' interface FileUploadParams { file: File onProgressCallback: (progress: number) => void onSuccessCallback: (res: { id: string }) => void onErrorCallback: () => void } type FileUpload = (v: FileUploadParams, isPublic?: boolean, url?: string) => void export const fileUpload: FileUpload = ({ file, onProgressCallback, onSuccessCallback, onErrorCallback, }) => { const formData = new FormData() formData.append('file', file) const onProgress = (e: ProgressEvent) => { if (e.lengthComputable) { const percent = Math.floor(e.loaded / e.total * 100) onProgressCallback(percent) } } upload({ xhr: new XMLHttpRequest(), data: formData, onprogress: onProgress, }) .then((res: { id: string }) => { onSuccessCallback(res) }) .catch(() => { onErrorCallback() }) } export const getFileExtension = (fileName: string, fileMimetype: string, isRemote?: boolean) => { let extension = '' if (fileMimetype) { extension = mime.getExtension(fileMimetype) || '' } if (fileName && !extension) { const fileNamePair = fileName.split('.') const fileNamePairLength = fileNamePair.length if (fileNamePairLength > 1) { extension = fileNamePair[fileNamePairLength - 1] } else { extension = '' } } if (isRemote) { extension = '' } return extension } export const getFileAppearanceType = (fileName: string, fileMimetype: string) => { const extension = getFileExtension(fileName, fileMimetype) if (extension === 'gif') { return FileAppearanceTypeEnum.gif } if (FILE_EXTS.image.includes(extension.toUpperCase())) { return FileAppearanceTypeEnum.image } if (FILE_EXTS.video.includes(extension.toUpperCase())) { return FileAppearanceTypeEnum.video } if (FILE_EXTS.audio.includes(extension.toUpperCase())) { return FileAppearanceTypeEnum.audio } if (extension === 'html') { return FileAppearanceTypeEnum.code } if (extension === 'pdf') { return FileAppearanceTypeEnum.pdf } if (extension === 'md' || extension === 'markdown' || extension === 'mdx') { return FileAppearanceTypeEnum.markdown } if (extension === 'xlsx' || extension === 'xls') { return FileAppearanceTypeEnum.excel } if (extension === 'docx' || extension === 'doc') { return FileAppearanceTypeEnum.word } if (extension === 'pptx' || extension === 'ppt') { return FileAppearanceTypeEnum.ppt } if (FILE_EXTS.document.includes(extension.toUpperCase())) { return FileAppearanceTypeEnum.document } return FileAppearanceTypeEnum.custom } export const getSupportFileType = (fileName: string, fileMimetype: string, isCustom?: boolean) => { if (isCustom) { return SupportUploadFileTypes.custom } const extension = getFileExtension(fileName, fileMimetype) for (const key in FILE_EXTS) { if ((FILE_EXTS[key]).includes(extension.toUpperCase())) { return key } } return '' } export const getProcessedFiles = (files: FileEntity[]) => { return files.filter(file => file.progress !== -1).map(fileItem => ({ type: fileItem.supportFileType, transfer_method: fileItem.transferMethod, url: fileItem.url || '', upload_file_id: fileItem.uploadedId || '', })) } export const getProcessedFilesFromResponse = (files: FileResponse[]) => { return files.map((fileItem) => { return { id: fileItem.related_id, name: fileItem.filename, size: fileItem.size || 0, type: fileItem.mime_type, progress: 100, transferMethod: fileItem.transfer_method, supportFileType: fileItem.type, uploadedId: fileItem.related_id, url: fileItem.url, } }) } export const getFileNameFromUrl = (url: string) => { const urlParts = url.split('/') return urlParts[urlParts.length - 1] || '' } export const getSupportFileExtensionList = (allowFileTypes: string[], allowFileExtensions: string[]) => { if (allowFileTypes.includes(SupportUploadFileTypes.custom)) { return allowFileExtensions.map(item => item.slice(1).toUpperCase()) } return allowFileTypes.map(type => FILE_EXTS[type]).flat() } export const isAllowedFileExtension = (fileName: string, fileMimetype: string, allowFileTypes: string[], allowFileExtensions: string[]) => { return getSupportFileExtensionList(allowFileTypes, allowFileExtensions).includes(getFileExtension(fileName, fileMimetype).toUpperCase()) } export const getFilesInLogs = (rawData: any) => { const result = Object.keys(rawData || {}).map((key) => { if (typeof rawData[key] === 'object' && rawData[key]?.dify_model_identity === '__dify__file__') { return { varName: key, list: getProcessedFilesFromResponse([rawData[key]]), } } if (Array.isArray(rawData[key]) && rawData[key].some(item => item?.dify_model_identity === '__dify__file__')) { return { varName: key, list: getProcessedFilesFromResponse(rawData[key]), } } return undefined }).filter(Boolean) return result } export const fileIsUploaded = (file: FileEntity) => { if (file.uploadedId) { return true } if (file.transferMethod === TransferMethod.remote_url && file.progress === 100) { return true } } export const downloadFile = (url: string, filename: string) => { const anchor = document.createElement('a') anchor.href = url anchor.download = filename anchor.style.display = 'none' anchor.target = '_blank' anchor.title = filename document.body.appendChild(anchor) anchor.click() document.body.removeChild(anchor) }