import mime from 'mime' import { flatten } from 'lodash-es' import { FileAppearanceTypeEnum } from './types' import type { FileEntity } from './types' import { upload } from '@/service/base' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import type { FileResponse } from '@/types/workflow' import { TransferMethod } from '@/types/app' type 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, }, isPublic, url) => { 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, }, isPublic, url) .then((res: { id: string }) => { onSuccessCallback(res) }) .catch(() => { onErrorCallback() }) } export const getFileExtension = (fileName: string, fileMimetype: string, isRemote?: boolean) => { if (fileMimetype) return mime.getExtension(fileMimetype) || '' if (isRemote) return '' if (fileName) { const fileNamePair = fileName.split('.') const fileNamePairLength = fileNamePair.length if (fileNamePairLength > 1) return fileNamePair[fileNamePairLength - 1] } return '' } 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') 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.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 originalFiles = flatten(Object.keys(rawData || {}).map((key) => { if (typeof rawData[key] === 'object' || Array.isArray(rawData[key])) return rawData[key] return undefined }).filter(Boolean)).filter(item => item?.model_identity === '__dify__file__') return getProcessedFilesFromResponse(originalFiles) } 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) }