Spaces:
Build error
Build error
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) | |
} | |