mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-13 18:55:58 +08:00
fix: upload remote image preview (#9952)
This commit is contained in:
parent
82033af097
commit
78b74cce8e
@ -1,6 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
memo,
|
memo,
|
||||||
useMemo,
|
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import {
|
import {
|
||||||
RiDeleteBinLine,
|
RiDeleteBinLine,
|
||||||
@ -35,17 +34,9 @@ const FileInAttachmentItem = ({
|
|||||||
onRemove,
|
onRemove,
|
||||||
onReUpload,
|
onReUpload,
|
||||||
}: FileInAttachmentItemProps) => {
|
}: FileInAttachmentItemProps) => {
|
||||||
const { id, name, type, progress, supportFileType, base64Url, url } = file
|
const { id, name, type, progress, supportFileType, base64Url, url, isRemote } = file
|
||||||
const ext = getFileExtension(name, type)
|
const ext = getFileExtension(name, type, isRemote)
|
||||||
const isImageFile = supportFileType === SupportUploadFileTypes.image
|
const isImageFile = supportFileType === SupportUploadFileTypes.image
|
||||||
const nameArr = useMemo(() => {
|
|
||||||
const nameMatch = name.match(/(.+)\.([^.]+)$/)
|
|
||||||
|
|
||||||
if (nameMatch)
|
|
||||||
return [nameMatch[1], nameMatch[2]]
|
|
||||||
|
|
||||||
return [name, '']
|
|
||||||
}, [name])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
@ -75,12 +66,7 @@ const FileInAttachmentItem = ({
|
|||||||
className='flex items-center mb-0.5 system-xs-medium text-text-secondary truncate'
|
className='flex items-center mb-0.5 system-xs-medium text-text-secondary truncate'
|
||||||
title={file.name}
|
title={file.name}
|
||||||
>
|
>
|
||||||
<div className='truncate'>{nameArr[0]}</div>
|
<div className='truncate'>{name}</div>
|
||||||
{
|
|
||||||
nameArr[1] && (
|
|
||||||
<span>.{nameArr[1]}</span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center system-2xs-medium-uppercase text-text-tertiary'>
|
<div className='flex items-center system-2xs-medium-uppercase text-text-tertiary'>
|
||||||
{
|
{
|
||||||
@ -93,7 +79,11 @@ const FileInAttachmentItem = ({
|
|||||||
<span className='mx-1 system-2xs-medium'>•</span>
|
<span className='mx-1 system-2xs-medium'>•</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<span>{formatFileSize(file.size || 0)}</span>
|
{
|
||||||
|
!!file.size && (
|
||||||
|
<span>{formatFileSize(file.size)}</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='shrink-0 flex items-center'>
|
<div className='shrink-0 flex items-center'>
|
||||||
|
@ -31,8 +31,8 @@ const FileItem = ({
|
|||||||
onRemove,
|
onRemove,
|
||||||
onReUpload,
|
onReUpload,
|
||||||
}: FileItemProps) => {
|
}: FileItemProps) => {
|
||||||
const { id, name, type, progress, url } = file
|
const { id, name, type, progress, url, isRemote } = file
|
||||||
const ext = getFileExtension(name, type)
|
const ext = getFileExtension(name, type, isRemote)
|
||||||
const uploadError = progress === -1
|
const uploadError = progress === -1
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -75,7 +75,9 @@ const FileItem = ({
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{formatFileSize(file.size || 0)}
|
{
|
||||||
|
!!file.size && formatFileSize(file.size)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
showDownloadAction && (
|
showDownloadAction && (
|
||||||
|
@ -25,7 +25,7 @@ import { TransferMethod } from '@/types/app'
|
|||||||
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
||||||
import type { FileUpload } from '@/app/components/base/features/types'
|
import type { FileUpload } from '@/app/components/base/features/types'
|
||||||
import { formatFileSize } from '@/utils/format'
|
import { formatFileSize } from '@/utils/format'
|
||||||
import { fetchRemoteFileInfo } from '@/service/common'
|
import { uploadRemoteFileInfo } from '@/service/common'
|
||||||
import type { FileUploadConfigResponse } from '@/models/common'
|
import type { FileUploadConfigResponse } from '@/models/common'
|
||||||
|
|
||||||
export const useFileSizeLimit = (fileUploadConfig?: FileUploadConfigResponse) => {
|
export const useFileSizeLimit = (fileUploadConfig?: FileUploadConfigResponse) => {
|
||||||
@ -49,7 +49,7 @@ export const useFile = (fileConfig: FileUpload) => {
|
|||||||
const params = useParams()
|
const params = useParams()
|
||||||
const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit(fileConfig.fileUploadConfig)
|
const { imgSizeLimit, docSizeLimit, audioSizeLimit, videoSizeLimit } = useFileSizeLimit(fileConfig.fileUploadConfig)
|
||||||
|
|
||||||
const checkSizeLimit = (fileType: string, fileSize: number) => {
|
const checkSizeLimit = useCallback((fileType: string, fileSize: number) => {
|
||||||
switch (fileType) {
|
switch (fileType) {
|
||||||
case SupportUploadFileTypes.image: {
|
case SupportUploadFileTypes.image: {
|
||||||
if (fileSize > imgSizeLimit) {
|
if (fileSize > imgSizeLimit) {
|
||||||
@ -120,7 +120,7 @@ export const useFile = (fileConfig: FileUpload) => {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}, [audioSizeLimit, docSizeLimit, imgSizeLimit, notify, t, videoSizeLimit])
|
||||||
|
|
||||||
const handleAddFile = useCallback((newFile: FileEntity) => {
|
const handleAddFile = useCallback((newFile: FileEntity) => {
|
||||||
const {
|
const {
|
||||||
@ -188,6 +188,17 @@ export const useFile = (fileConfig: FileUpload) => {
|
|||||||
}
|
}
|
||||||
}, [fileStore, notify, t, handleUpdateFile, params])
|
}, [fileStore, notify, t, handleUpdateFile, params])
|
||||||
|
|
||||||
|
const startProgressTimer = useCallback((fileId: string) => {
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
const files = fileStore.getState().files
|
||||||
|
const file = files.find(file => file.id === fileId)
|
||||||
|
|
||||||
|
if (file && file.progress < 80 && file.progress >= 0)
|
||||||
|
handleUpdateFile({ ...file, progress: file.progress + 20 })
|
||||||
|
else
|
||||||
|
clearTimeout(timer)
|
||||||
|
}, 200)
|
||||||
|
}, [fileStore, handleUpdateFile])
|
||||||
const handleLoadFileFromLink = useCallback((url: string) => {
|
const handleLoadFileFromLink = useCallback((url: string) => {
|
||||||
const allowedFileTypes = fileConfig.allowed_file_types
|
const allowedFileTypes = fileConfig.allowed_file_types
|
||||||
|
|
||||||
@ -197,19 +208,27 @@ export const useFile = (fileConfig: FileUpload) => {
|
|||||||
type: '',
|
type: '',
|
||||||
size: 0,
|
size: 0,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
transferMethod: TransferMethod.remote_url,
|
transferMethod: TransferMethod.local_file,
|
||||||
supportFileType: '',
|
supportFileType: '',
|
||||||
url,
|
url,
|
||||||
|
isRemote: true,
|
||||||
}
|
}
|
||||||
handleAddFile(uploadingFile)
|
handleAddFile(uploadingFile)
|
||||||
|
startProgressTimer(uploadingFile.id)
|
||||||
|
|
||||||
fetchRemoteFileInfo(url).then((res) => {
|
uploadRemoteFileInfo(url).then((res) => {
|
||||||
const newFile = {
|
const newFile = {
|
||||||
...uploadingFile,
|
...uploadingFile,
|
||||||
type: res.file_type,
|
type: res.mime_type,
|
||||||
size: res.file_length,
|
size: res.size,
|
||||||
progress: 100,
|
progress: 100,
|
||||||
supportFileType: getSupportFileType(url, res.file_type, allowedFileTypes?.includes(SupportUploadFileTypes.custom)),
|
supportFileType: getSupportFileType(res.name, res.mime_type, allowedFileTypes?.includes(SupportUploadFileTypes.custom)),
|
||||||
|
uploadedId: res.id,
|
||||||
|
url: res.url,
|
||||||
|
}
|
||||||
|
if (!isAllowedFileExtension(res.name, res.mime_type, fileConfig.allowed_file_types || [], fileConfig.allowed_file_extensions || [])) {
|
||||||
|
notify({ type: 'error', message: t('common.fileUploader.fileExtensionNotSupport') })
|
||||||
|
handleRemoveFile(uploadingFile.id)
|
||||||
}
|
}
|
||||||
if (!checkSizeLimit(newFile.supportFileType, newFile.size))
|
if (!checkSizeLimit(newFile.supportFileType, newFile.size))
|
||||||
handleRemoveFile(uploadingFile.id)
|
handleRemoveFile(uploadingFile.id)
|
||||||
@ -219,7 +238,7 @@ export const useFile = (fileConfig: FileUpload) => {
|
|||||||
notify({ type: 'error', message: t('common.fileUploader.pasteFileLinkInvalid') })
|
notify({ type: 'error', message: t('common.fileUploader.pasteFileLinkInvalid') })
|
||||||
handleRemoveFile(uploadingFile.id)
|
handleRemoveFile(uploadingFile.id)
|
||||||
})
|
})
|
||||||
}, [checkSizeLimit, handleAddFile, handleUpdateFile, notify, t, handleRemoveFile, fileConfig?.allowed_file_types])
|
}, [checkSizeLimit, handleAddFile, handleUpdateFile, notify, t, handleRemoveFile, fileConfig?.allowed_file_types, fileConfig.allowed_file_extensions, startProgressTimer])
|
||||||
|
|
||||||
const handleLoadFileFromLinkSuccess = useCallback(() => { }, [])
|
const handleLoadFileFromLinkSuccess = useCallback(() => { }, [])
|
||||||
|
|
||||||
|
@ -29,4 +29,5 @@ export type FileEntity = {
|
|||||||
uploadedId?: string
|
uploadedId?: string
|
||||||
base64Url?: string
|
base64Url?: string
|
||||||
url?: string
|
url?: string
|
||||||
|
isRemote?: boolean
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,13 @@ export const fileUpload: FileUpload = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFileExtension = (fileName: string, fileMimetype: string) => {
|
export const getFileExtension = (fileName: string, fileMimetype: string, isRemote?: boolean) => {
|
||||||
if (fileMimetype)
|
if (fileMimetype)
|
||||||
return mime.getExtension(fileMimetype) || ''
|
return mime.getExtension(fileMimetype) || ''
|
||||||
|
|
||||||
|
if (isRemote)
|
||||||
|
return ''
|
||||||
|
|
||||||
if (fileName) {
|
if (fileName) {
|
||||||
const fileNamePair = fileName.split('.')
|
const fileNamePair = fileName.split('.')
|
||||||
const fileNamePairLength = fileNamePair.length
|
const fileNamePairLength = fileNamePair.length
|
||||||
|
@ -133,6 +133,7 @@ const ImageList: FC<ImageListProps> = ({
|
|||||||
<ImagePreview
|
<ImagePreview
|
||||||
url={imagePreviewUrl}
|
url={imagePreviewUrl}
|
||||||
onCancel={() => setImagePreviewUrl('')}
|
onCancel={() => setImagePreviewUrl('')}
|
||||||
|
title=''
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -324,9 +324,10 @@ export const verifyForgotPasswordToken: Fetcher<CommonResponse & { is_valid: boo
|
|||||||
export const changePasswordWithToken: Fetcher<CommonResponse, { url: string; body: { token: string; new_password: string; password_confirm: string } }> = ({ url, body }) =>
|
export const changePasswordWithToken: Fetcher<CommonResponse, { url: string; body: { token: string; new_password: string; password_confirm: string } }> = ({ url, body }) =>
|
||||||
post<CommonResponse>(url, { body })
|
post<CommonResponse>(url, { body })
|
||||||
|
|
||||||
export const fetchRemoteFileInfo = (url: string) => {
|
export const uploadRemoteFileInfo = (url: string) => {
|
||||||
return get<{ file_type: string; file_length: number }>(`/remote-files/${url}`)
|
return post<{ id: string; name: string; size: number; mime_type: string; url: string }>('/remote-files/upload', { body: { url } })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sendEMailLoginCode = (email: string, language = 'en-US') =>
|
export const sendEMailLoginCode = (email: string, language = 'en-US') =>
|
||||||
post<CommonResponse & { data: string }>('/email-code-login', { body: { email, language } })
|
post<CommonResponse & { data: string }>('/email-code-login', { body: { email, language } })
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user