antd upload自定义上传(customRequest)

3,814 阅读1分钟

自定义上传oss,待后端返回上传地址,利用axios.put上传 ,uploa组件内置请求是formdata 无法满足

//import UploadOss,{transUrlsToFileList} from '../../../components/UploadOss'

import React, { useState, } from 'react';
import { Upload, Button, message, Form } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import request, { ResponseDataType } from '@/utils/request';
import axios from 'axios'
/* eg:
         <UploadOss
          formItem={{
            name:'page_background',
            label:'权益背景图',
          }}
             imgUrl={bgUrl}
             setImgUrl={setBgUrl}        
             />
*/

let cdnUrl = ''
let uuid = ''
const REG_IMG_TYPE = /\/\w+\.(jfif|png|jpg|gif|pdf|jpeg)/i;
//[urls],初始化url
export function transUrlsToFileList(urls) {
	if (!Array.isArray(urls)) return [];
	const fileObjs: any[] = [];
	for (let i = 0; i < urls.length; i += 1) {
		const url_i = urls[i];
		if (url_i) {
			const fileNameMatch = url_i.match(REG_IMG_TYPE) || [url_i];
			if (fileNameMatch) {
				// let arr=fileNameMatch[0].split("_")
				// console.log(fileNameMatch[0],fileNameMatch[0].split("_"))
				fileObjs.push({
					uid: Date.now(),
					name: fileNameMatch[0],
					status: 'done',
					url: url_i,
				});
			}
		}
	}
	return fileObjs;
}
//上传图片地址修改
export function changeFile(field: any) {
	if (!field || field.length === 0) {
		return undefined
	}
	const fileObj = field[0]
	if (field && typeof field == 'string') {
		return field
	} else if (field.length && field[0].response) {
		return fileObj.response.url
	} else {
		throw new Error('获取不到上传文件')
	}
}

//获取上传oss地址
async function uploadFile(
	item: { objectName: string, dir: string },
) {
	const res: ResponseDataType = await request.post(`/api/op/file/oss/path`, {
		...item,
	});
	return res;
}
//uuid,前端独立文件名
function generateUUID() {
	var d = new Date().getTime();
	if (window.performance && typeof window.performance.now === "function") {
		d += performance.now(); //use high-precision timer if available
	}
	var uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
		var r = (d + Math.random() * 16) % 16 | 0;
		d = Math.floor(d / 16);
		return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
	});
	return uuid;
}

interface FormItem {
	name: string
	label: string
	[index: string]: string | {}
}

type Props = {
	imgUrl: any[]
	formItem: FormItem
	setImgUrl: (value) => void;
	dir: string  //  eg:xxx/xxx/xxx/
	beforeUpload?: (file) => any
};

const UploadOss: React.FC<Props> = (props) => {
	const { imgUrl, formItem, setImgUrl, dir, beforeUpload = () => { } } = props
	const normFile = (e) => {
		if (Array.isArray(e)) {
			return e;
		}
		if (e.file && e.file.status === 'done') {
			const resp = e.file.response
			if (resp && !resp.result_status) {
				message.error(resp.error_desc || '抱歉,上传服务发送未知错误.')
				setImgUrl([])
				return []
			}
		}

		let fileList = (e && e.fileList) || []
		if (fileList && e.fileList.length > 1) {
			fileList = fileList.filter(file => !file.error)
		}
		// 同步
		if (e.fileList && e.fileList.length === 0) {
			setImgUrl([])  // 删除
		} else if (e.file.status === 'done' && e.file.response) {
			e.file.thumbUrl = e.file.response.url
			setImgUrl([e.file])
		} else if (e.file.status === 'uploading') {
			setImgUrl([e.file])
		}
		return fileList;
	};

	return (
		<Form.Item
			{...formItem}
			getValueFromEvent={(e) => normFile(e)}
		>
			<Upload
				fileList={imgUrl}
				action={
					(file) => new Promise(async (resolve) => {
						uuid = generateUUID() + '_' + file.name
						const res: ResponseDataType = await uploadFile({
							objectName: uuid,
							dir,
						})
						if (res && res.result_status) {
							resolve(res.data.url)
							cdnUrl = res.data.cdnUrl
						} else {
							message.error('获取上传oss地址失败')
						}

					})
				}
				customRequest={
					(e) => {
						const { action, file, onError, onProgress, onSuccess } = e
						// 	var file = new File([e.file],uuid, {
						// 		type: e.file.type
						// });
						axios.put(action, file, {// 显示进度
							headers: { 'Content-Type': 'application/octet-stream' },
							onUploadProgress: (ev) => {
								const percent = ((ev.loaded / ev.total) * 100) | 0;
								onProgress({ percent, }, file,);
							},
						}).then(() => {
							// const url=`${cdnUrl}/${dir}${uuid}`
							const url =cdnUrl+'/'+dir+uuid
							onSuccess({ result_status: true, url, }, file,);
						},
							(res) => {
								onError(res);
							},
						);
					}
				}
				listType="picture"
				accept="image/*"
				method='PUT'
				beforeUpload={(file, fileList) => beforeUpload(file)}
			>
				{imgUrl.length > 0 ? null : (
					<Button>
						<UploadOutlined /> 上传图片
					</Button>
				)}
			</Upload>
		</Form.Item>
	)
}
export default UploadOss