asb_cloud_front/src/components/UploadForm.tsx

93 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { UploadFile } from 'antd/lib/upload/interface'
import { UploadOutlined } from '@ant-design/icons'
import { RcFile } from 'antd/lib/upload'
import { Upload, Button } from 'antd'
import { isDev } from '@utils'
import { notify, upload } from './factory'
import { ErrorFetch } from './ErrorFetch'
export type UploadFormProps = {
multiple?: boolean
url: string
disabled?: boolean
accept?: string
mimeTypes?: string | string[]
style?: CSSStyleSheet
formData: FormData
onUploadStart?: () => void
onUploadSuccess?: () => void
onUploadComplete?: () => void
onUploadError?: (error: unknown) => void
}
export const UploadForm = memo<UploadFormProps>(({ url, multiple, disabled, style, formData, mimeTypes, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError }) => {
const [fileList, setfileList] = useState<UploadFile<any>[]>([])
const checkMimeTypes = useCallback((file: RcFile) => {
const isAccepted = !mimeTypes || mimeTypes.includes(file.type)
if (isAccepted) return false
notify(`"${file.name}" является файлом неподходящего типа`, 'error')
return Upload.LIST_IGNORE
}, [mimeTypes])
const accept = useMemo(() => Array.isArray(mimeTypes) ? mimeTypes.join(',') : mimeTypes, [mimeTypes])
const handleFileSend = useCallback(async () => {
onUploadStart?.()
try {
const formDataLocal = new FormData()
fileList.forEach((val) => formDataLocal.append(multiple ? 'files' : 'file', val.originFileObj as Blob))
if(formData)
for(const propName in formData)
formDataLocal.append(propName, String(formData.get(propName)))
const response = await upload(url, formDataLocal)
if (!response.ok) {
const errorText = await response.text()
const error = new ErrorFetch(response.status, errorText)
throw error
} else {
onUploadSuccess?.()
}
} catch(error) {
if(isDev())
console.error(error)
onUploadError?.(error)
} finally {
setfileList([])
onUploadComplete?.()
}
}, [fileList, formData, onUploadComplete, onUploadError, onUploadStart, onUploadSuccess, url, multiple])
const isSendButtonEnabled = fileList.length > 0
return(
<div style={{ display: 'flex', ...style }}>
<Upload
name={'file'}
accept={accept}
disabled={disabled}
fileList={fileList}
onChange={(props) => setfileList(props.fileList)}
beforeUpload={checkMimeTypes}
maxCount={multiple ? undefined : 1}
>
<Button disabled={disabled} icon={<UploadOutlined/>}>Загрузить файл</Button>
</Upload>
<Button
type={'primary'}
onClick={handleFileSend}
disabled={!isSendButtonEnabled}
style={{ marginLeft: '10px', display: isSendButtonEnabled ? '' : 'none' }}
>
Отправить
</Button>
</div>
)
})
export default UploadForm