2022-05-18 17:18:35 +05:00
|
|
|
|
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
2022-04-29 16:39:49 +05:00
|
|
|
|
import { UploadFile } from 'antd/lib/upload/interface'
|
2022-06-02 14:45:28 +05:00
|
|
|
|
import { UploadOutlined } from '@ant-design/icons'
|
2022-05-18 17:18:35 +05:00
|
|
|
|
import { RcFile } from 'antd/lib/upload'
|
2022-06-02 14:45:28 +05:00
|
|
|
|
import { Upload, Button } from 'antd'
|
|
|
|
|
|
|
|
|
|
import { isDev } from '@utils'
|
2022-01-24 21:16:50 +05:00
|
|
|
|
|
2022-05-18 17:18:35 +05:00
|
|
|
|
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
|
|
|
|
|
2022-04-29 16:39:49 +05:00
|
|
|
|
export type UploadFormProps = {
|
2022-09-13 16:17:32 +05:00
|
|
|
|
multiple?: boolean
|
2022-04-29 16:39:49 +05:00
|
|
|
|
url: string
|
|
|
|
|
disabled?: boolean
|
|
|
|
|
accept?: string
|
2022-05-18 17:18:35 +05:00
|
|
|
|
mimeTypes?: string | string[]
|
2022-04-29 16:39:49 +05:00
|
|
|
|
style?: CSSStyleSheet
|
|
|
|
|
formData: FormData
|
|
|
|
|
onUploadStart?: () => void
|
|
|
|
|
onUploadSuccess?: () => void
|
|
|
|
|
onUploadComplete?: () => void
|
|
|
|
|
onUploadError?: (error: unknown) => void
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 16:17:32 +05:00
|
|
|
|
export const UploadForm = memo<UploadFormProps>(({ url, multiple, disabled, style, formData, mimeTypes, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError }) => {
|
2022-04-29 16:39:49 +05:00
|
|
|
|
const [fileList, setfileList] = useState<UploadFile<any>[]>([])
|
2021-08-17 10:46:28 +05:00
|
|
|
|
|
2022-05-18 17:18:35 +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])
|
|
|
|
|
|
2022-02-25 16:57:08 +05:00
|
|
|
|
const handleFileSend = useCallback(async () => {
|
2022-01-24 21:16:50 +05:00
|
|
|
|
onUploadStart?.()
|
2021-08-17 10:46:28 +05:00
|
|
|
|
try {
|
2021-10-11 13:41:54 +05:00
|
|
|
|
const formDataLocal = new FormData()
|
2022-09-13 16:17:32 +05:00
|
|
|
|
fileList.forEach((val) => formDataLocal.append(multiple ? 'files' : 'file', val.originFileObj as Blob))
|
2021-10-11 13:41:54 +05:00
|
|
|
|
|
|
|
|
|
if(formData)
|
2022-01-24 21:16:50 +05:00
|
|
|
|
for(const propName in formData)
|
2022-04-29 16:39:49 +05:00
|
|
|
|
formDataLocal.append(propName, String(formData.get(propName)))
|
2022-01-24 21:16:50 +05:00
|
|
|
|
|
2021-10-11 13:41:54 +05:00
|
|
|
|
const response = await upload(url, formDataLocal)
|
2022-01-24 21:16:50 +05:00
|
|
|
|
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
|
2022-01-24 21:16:50 +05:00
|
|
|
|
} else {
|
|
|
|
|
onUploadSuccess?.()
|
2021-10-11 13:41:54 +05:00
|
|
|
|
}
|
2021-08-17 10:46:28 +05:00
|
|
|
|
} catch(error) {
|
2022-06-02 14:45:28 +05:00
|
|
|
|
if(isDev())
|
2022-02-22 15:28:55 +05:00
|
|
|
|
console.error(error)
|
2022-01-24 21:16:50 +05:00
|
|
|
|
onUploadError?.(error)
|
2021-08-17 10:46:28 +05:00
|
|
|
|
} finally {
|
2021-08-17 16:46:46 +05:00
|
|
|
|
setfileList([])
|
2022-01-24 21:16:50 +05:00
|
|
|
|
onUploadComplete?.()
|
2021-08-17 10:46:28 +05:00
|
|
|
|
}
|
2022-09-13 16:17:32 +05:00
|
|
|
|
}, [fileList, formData, onUploadComplete, onUploadError, onUploadStart, onUploadSuccess, url, multiple])
|
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(
|
2022-01-24 21:16:50 +05:00
|
|
|
|
<div style={{ display: 'flex', ...style }}>
|
|
|
|
|
<Upload
|
|
|
|
|
name={'file'}
|
2021-09-01 10:32:47 +05:00
|
|
|
|
accept={accept}
|
2022-02-22 15:28:55 +05:00
|
|
|
|
disabled={disabled}
|
2022-01-24 21:16:50 +05:00
|
|
|
|
fileList={fileList}
|
|
|
|
|
onChange={(props) => setfileList(props.fileList)}
|
2022-05-18 17:18:35 +05:00
|
|
|
|
beforeUpload={checkMimeTypes}
|
2022-09-13 16:17:32 +05:00
|
|
|
|
maxCount={multiple ? undefined : 1}
|
2022-01-24 21:16:50 +05:00
|
|
|
|
>
|
2022-02-22 15:28:55 +05:00
|
|
|
|
<Button disabled={disabled} icon={<UploadOutlined/>}>Загрузить файл</Button>
|
2021-08-17 16:46:46 +05:00
|
|
|
|
</Upload>
|
2022-01-24 21:16:50 +05:00
|
|
|
|
<Button
|
|
|
|
|
type={'primary'}
|
|
|
|
|
onClick={handleFileSend}
|
2021-08-17 16:46:46 +05:00
|
|
|
|
disabled={!isSendButtonEnabled}
|
2022-01-24 21:16:50 +05:00
|
|
|
|
style={{ marginLeft: '10px', display: isSendButtonEnabled ? '' : 'none' }}
|
|
|
|
|
>
|
2021-08-17 16:46:46 +05:00
|
|
|
|
Отправить
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
2021-08-17 10:46:28 +05:00
|
|
|
|
)
|
2022-01-24 21:16:50 +05:00
|
|
|
|
})
|
2022-02-24 15:42:26 +05:00
|
|
|
|
|
|
|
|
|
export default UploadForm
|