【上传组件】react-dropzone-component VS react-filepond
1. react-dropzone-component
写一个名为MultiFilesUpload.js组件
// @flow import React from 'react'; import Dropzone from 'react-dropzone-component'; import { Button, Icon } from 'semantic-ui-react'; import { withAlert } from 'react-alert'; import withFetch from './hoc/withFetch'; type Props= { uploadUrl: string, disabled: boolean, minHeight?: string, message: string, fileType: string, hideBtn: boolean, // 是否隐藏按钮 maxFiles: number, // 上传的最大文件数 contentFiles: number, // 上传的当前文件数 alert: () => void, alerts: () => void, acceptedFiles: string, // 限制文件格式 btnMeg?: string, // 按钮的文案, 默认为上传 btnClassName: string, // 按钮的类名, 支持父元素传递的样式 onFileUploaded: (result: Object) => void, onFileDeleted: (file: Object) => void, onLoading: (onLoading: boolean) => void, } type State= { onLoading: boolean, } export class MultiFilesUpload extends React.PureComponent{ defaultProps: Props maxFilesExceeded: (file: Object) => void handleUpload: Function handleRemove: (file: Object) => void eventHandlers: Object dropzone: Object djsConfig: Object static defaultProps = { uploadUrl: 'k2data.com', minHeight: '36px', maxFiles: 60, disabled: false, btnMeg: '上传', } constructor(props: Props) { super(props); this.state = { onLoading: false, }; this.maxFilesExceeded = this.maxFilesExceeded.bind(this); this.handleUpload = this.handleUpload.bind(this); this.handleRemove = this.handleRemove.bind(this); this.djsConfig = { autoProcessQueue: false, addRemoveLinks: true, acceptedFiles: this.props.acceptedFiles, maxFiles: props.maxFiles, dictRemoveFile: '删除文件', }; this.eventHandlers = { init: (dropzone) => { this.dropzone = dropzone; }, // maxfilesexceeded: this.maxFilesExceeded, addedfile: this.handleUpload, removedfile: this.handleRemove, }; } maxFilesExceeded(file: Object) { this.dropzone.removeFile(file); if (this.props.alert) { this.props.alert.error('达到最大上传文件数', { timeout: 3000, }); } else { this.props.alerts.error('达到最大上传文件数', { timeout: 3000, }); } } handleUpload = async (file) => { const { onFileUploaded, fileType = 'contract', contentFiles, maxFiles, } = this.props; // 限制文件大小 // if (size > 300000) { // this.props.alert.error('上传文件大小超限'); // return; // } // 到达最大个数后不执行上传 if (file.name.indexOf('&') !== -1 || file.name.indexOf('/') !== -1 || file.name.indexOf('\\') !== -1) { if (this.props.alert) { this.props.alert.error('不能含有特殊字符"&"/""\\"'); } else { this.props.alerts.error('不能含有特殊字符"&"/""\\"'); } return; } if (contentFiles && contentFiles >= maxFiles) { if (this.props.alert) { this.props.alert.error('达到最大上传文件数'); } else { this.props.alerts.error('达到最大上传文件数'); } return; } this.setState({ onLoading: true }); if (this.props.onLoading) { this.props.onLoading(true); } const data = new FormData(); data.append(`${fileType}`, file); const body = { method: 'POST', body: data, }; const { fetchWithUser, handleFetchError } = this.props; try { const json = await fetchWithUser(this.props.uploadUrl, body); // eslint-disable-next-line file.response = json if (typeof onFileUploaded === 'function') { onFileUploaded(json); this.setState({ onLoading: false }); if (this.props.onLoading) { this.props.onLoading(false); } } } catch (e) { const mes = `上传失败:${e.message}`; if (this.props.alert) { this.props.alert.error(mes, { timeout: 3000, }); } else { this.props.alerts.error(mes, { timeout: 3000, }); } this.setState({ onLoading: false }); if (this.props.onLoading) { this.props.onLoading(false); } handleFetchError(e); } } handleRemove(file: Object) { const { onFileDeleted } = this.props; if (typeof onFileDeleted === 'function') { onFileDeleted(file.response); } } render() { const { minHeight, message, disabled, btnMeg, btnClassName, hideBtn, } = this.props; const { onLoading } = this.state; return ( ); } } export default withFetch(withAlert(MultiFilesUpload));{ hideBtn ? '' : (<Button basic className={btnClassName || 'uploadBtn'} disabled={disabled || onLoading} > {btnMeg} { !hideBtn && onLoading ?{message}: '' } ) } { // !hideBtn && onLoading // ? // : '' } { disabled || onLoading ? '' : (<Dropzone accept="image/jpeg, image/png" eventHandlers={this.eventHandlers} config={{ showFiletypeIcon: true, postUrl: 'no-url', }} djsConfig={this.djsConfig} />) }
页面中使用
import MultiFilesUpload from '../MultiFilesUpload'; <MultiFilesUpload uploadUrl={`${env.SERVICE_URL}/services/upload`} message="(建议尺寸100px*100px)" fileType="file" disabled={coverImg} acceptedFiles="image/*" onFileUploaded={this.handleCoverUpload} onFileDeleted={this.handleCoverDelete} maxFiles={1} contentFiles={coverImg ? 1 : 0} />
2. react-filepond
写一个Filepond.js组件
// @flow import React from 'react'; import { FilePond, File } from 'react-filepond'; import { connect } from 'react-redux'; import { withAlert } from 'react-alert'; type Props = { uploadUrl: string, token: string, fileType: string, deletUrl: string, onUploaded: Function, files: Array
页面中使用
import FilepondUpload from './Filepond'; <FilepondUpload uploadUrl={UPLOAD_URL} message="上传合同" fileType="contract" onUploaded={onUploaded} onError={this.repeatFileName} />