asb_cloud_front/src/components/UploadForm.tsx

91 lines
2.9 KiB
TypeScript
Raw Normal View History

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'
2021-10-11 13:41:54 +05:00
import { ErrorFetch } from './ErrorFetch'
2021-08-17 10:46:28 +05:00
export type UploadFormProps = {
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, disabled, style, formData, mimeTypes, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError }) => {
const [fileList, setfileList] = useState<UploadFile<any>[]>([])
2021-08-17 10:46:28 +05:00
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?.()
2021-08-17 10:46:28 +05:00
try {
2021-10-11 13:41:54 +05:00
const formDataLocal = new FormData()
fileList.forEach((val) => formDataLocal.append('files', val.originFileObj as Blob))
2021-10-11 13:41:54 +05:00
if(formData)
for(const propName in formData)
formDataLocal.append(propName, String(formData.get(propName)))
2021-10-11 13:41:54 +05:00
const response = await upload(url, formDataLocal)
if (!response.ok) {
const errorText = await response.text()
2021-10-11 13:41:54 +05:00
const error = new ErrorFetch(response.status, errorText)
throw error
} else {
onUploadSuccess?.()
2021-10-11 13:41:54 +05:00
}
2021-08-17 10:46:28 +05:00
} catch(error) {
if(isDev())
console.error(error)
onUploadError?.(error)
2021-08-17 10:46:28 +05:00
} finally {
2021-08-17 16:46:46 +05:00
setfileList([])
onUploadComplete?.()
2021-08-17 10:46:28 +05:00
}
}, [fileList, formData, onUploadComplete, onUploadError, onUploadStart, onUploadSuccess, url])
2021-08-17 10:46:28 +05:00
2021-08-17 16:46:46 +05:00
const isSendButtonEnabled = fileList.length > 0
2021-08-17 10:46:28 +05:00
return(
<div style={{ display: 'flex', ...style }}>
<Upload
name={'file'}
accept={accept}
disabled={disabled}
fileList={fileList}
onChange={(props) => setfileList(props.fileList)}
beforeUpload={checkMimeTypes}
>
<Button disabled={disabled} icon={<UploadOutlined/>}>Загрузить файл</Button>
2021-08-17 16:46:46 +05:00
</Upload>
<Button
type={'primary'}
onClick={handleFileSend}
2021-08-17 16:46:46 +05:00
disabled={!isSendButtonEnabled}
style={{ marginLeft: '10px', display: isSendButtonEnabled ? '' : 'none' }}
>
2021-08-17 16:46:46 +05:00
Отправить
</Button>
</div>
2021-08-17 10:46:28 +05:00
)
})
export default UploadForm