fix: upload remote image preview (#9952)

This commit is contained in:
zxhlyh 2024-11-01 15:45:27 +08:00 committed by GitHub
parent 82033af097
commit 78b74cce8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 50 additions and 33 deletions

View File

@ -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'>

View File

@ -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 && (

View File

@ -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(() => { }, [])

View File

@ -29,4 +29,5 @@ export type FileEntity = {
uploadedId?: string uploadedId?: string
base64Url?: string base64Url?: string
url?: string url?: string
isRemote?: boolean
} }

View File

@ -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

View File

@ -133,6 +133,7 @@ const ImageList: FC<ImageListProps> = ({
<ImagePreview <ImagePreview
url={imagePreviewUrl} url={imagePreviewUrl}
onCancel={() => setImagePreviewUrl('')} onCancel={() => setImagePreviewUrl('')}
title=''
/> />
)} )}
</div> </div>

View File

@ -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 } })