zoukankan      html  css  js  c++  java
  • 【上传组件】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<Props, State> {
      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 (
          <div className="fileInputCon">
            <div style={{ position: 'relative', display: 'inline-block' }}>
              {
                hideBtn ? ''
                : (<Button
                  basic
                  className={btnClassName || 'uploadBtn'}
                  disabled={disabled || onLoading}
                >
                  {btnMeg}
                  {
                    !hideBtn && onLoading
                    ? <Icon name="spinner" className="splnnerLoading" />
                    : ''
                  }
                </Button>)
              }
              {
                // !hideBtn && onLoading
                // ? <div className="upload-loader"><Loader active /></div>
                // : ''
              }
              {
                disabled || onLoading ? '' : (
                  <div className="container">
                    <Dropzone
                      accept="image/jpeg, image/png"
                      eventHandlers={this.eventHandlers}
                      config={{
                        showFiletypeIcon: true,
                        postUrl: 'no-url',
                      }}
                      djsConfig={this.djsConfig}
                    />
                  </div>
                )
              }
            </div>
            <span className="updataMes">{message}</span>
            <style jsx>{`
                .fileInputCon{
                  position: relative;
                  display: inline-block;
                }
                .container {
                  position: absolute;
                  left: 0;
                  right: 0;
                  top: 0;
                  bottom: 0;
                  opacity: 0;
                }
                .updataMes{
                  color: #999;
                  font-size: 12px;
                }
                .container :global(.filepicker.dropzone) {
                  position: relative;
                  text-align: center;
                  padding: 10px;
                  border: 1px dashed rgba(0,0,0,.1);
                  border-radius: 4px;
                  background: transparent;
                  min-height: ${minHeight || '36px'};
                  pointer-events: ${disabled ? 'none' : 'auto'};
                }
                .container :global(
                  .dropzone .dz-preview.dz-error .dz-error-message,
                  .dropzone .dz-preview.dz-error .dz-error-mark,
                  .dropzone .dz-preview .dz-progress,
                  .container .dropzone .dz-message,
                  .dropzone .dz-preview
                ) {
                  display: none;
                }
            `}
            </style>
            <style global jsx>{`
                button.ui.button.uploadBtn {
                  color: #009edc!important;
                  border: 1px solid #009edc;
                  box-shadow: none;
                  padding: 8px 0;
                   100px;
                }
                @keyframes button-spin {
                  from {
                    -webkit-transform: rotate(0deg);
                            transform: rotate(0deg);
                  }
                  to {
                    -webkit-transform: rotate(360deg);
                            transform: rotate(360deg);
                  }
                }
                i.icon.splnnerLoading{
                  margin-left: 5px!important;
                  -webkit-animation: button-spin 0.8s linear;
                  animation: button-spin 0.8s linear;
                  -webkit-animation-iteration-count: infinite;
                  animation-iteration-count: infinite;
                }
            `}
            </style>
          </div>
        );
      }
    }
    
    export default withFetch(withAlert(MultiFilesUpload));

    页面中使用

    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<Object>,
      onError?: Function,
      message?: string,
      alert: Object,
      onFileUploaded: Function, // 上传功能后执行的函数
    }
    
    type State = {
      files: Array<File>,
      progress: number,
    }
    
    export class FilepondUpload extends React.PureComponent<Props, State> {
      pond: any
      state = {
        files: [],
        progress: 1,
      }
    
      onprocessfileprogress = (file, progress) => {
        const { onUploaded } = this.props;
        this.setState({ progress });
        setTimeout(() => {
          if (onUploaded && progress === 1) {
            onUploaded();
          }
        }, 1000);
      }
    
      uploadConfig() {
        const { uploadUrl, token, deletUrl } = this.props;
        return {
          url: '',
          process: {
            url: uploadUrl,
            withCredentials: false,
            headers: {
              Authorization: `Bearer ${token}`,
            },
            onload: this.onload,
            onerror: this.onerror,
          },
          revert: {
            url: deletUrl,
            withCredentials: false,
            headers: {
              Authorization: `Bearer ${token}f`,
            },
          },
        };
      }
    
      onload = (e) => {
        console.log('上传成功后的response', e);
        if (this.props.onFileUploaded) {
          this.props.onFileUploaded(JSON.parse(e));
        }
      }
      onerror = (e) => {
        console.log('上传失败后的response', e);
      }
    
    
      handleError = (e) => {
        this.setState({ progress: 1 });
        if (this.props.onError) {
          this.props.onError(e);
        }
      }
    
      addFile = (e, file) => {
        const { filename } = file;
        if (filename.indexOf('&') !== -1 || filename.indexOf('/') !== -1 || filename.indexOf('\') !== -1) {
          this.props.alert.error('不能含有特殊字符"&"/""\"');
          file.abortProcessing();
          file.abortLoad();
          return null;
        }
      }
      processFile = (file) => {
        const { filename } = file;
        if (filename.indexOf('&') !== -1 || filename.indexOf('/') !== -1 || filename.indexOf('\') !== -1) {
          file.abortProcessing();
          file.abortLoad();
          return null;
        }
      }
    
      render() {
        const { files, progress } = this.state;
        const { fileType, message = '上传合同' } = this.props;
        const { onprocessfileprogress } = this;
        return (
          <div className="container-wraper">
            <div className="container">
              <div className="progress" >
                <progress value={progress} max="1" className="progress-bar" />
                <span>{parseInt(progress * 100, 10)}%</span>
              </div>
              <div className="upload">
                <FilePond {...{
                  maxFiles: 100,
                  labelIdle: message,
                  server: this.uploadConfig(),
                  name: fileType,
                  allowMultiple: true,
                  allowRevert: false,
                  instantUpload: true,
                  onprocessfileprogress,
                  onerror: this.handleError,
                  onaddfile: this.addFile,
                  onprocessfilestart: this.processFile,
                }}
                >
                  {files.map(file => (<File source={file} key={file} />))}
                </FilePond>
              </div>
            </div>
    
            <style jsx>{`
              .container-wraper {
                display: inline-block;
                 130px;
                height: 40px;
                cursor: pointer;
              }
              .container {
                position: relative;
              }
              .progress {
                position: absolute;
                top: 2px;
                line-height: 32px;
                z-index: ${progress === 1 ? 1 : 10};
                opacity: ${progress === 1 ? 0 : 1};
                height: 32px;
                 123px;
                left: 2px;
                background-color: white;
              }
              .progress-bar {
                 90px;
                transform: translateY(3px);
              }
              .upload {
                position: absolute;
                top: 0;
                z-index: 2;
                height: 33px;
              }
              .upload :global(.filepond--list-scroller) {
                transform:translate3d(0px, 34px, 0) !important;
                opacity: 0;
              }
              .upload:active{
                background: #009edc;
              }
              .text {
                position: absolute;
                top: 0;
                left: 0;
                bottom: 0;
                right: 0;
              }
            `}
            </style>
            <style jsx global>{`
              .filepond--root {
                height: 35px !important;
                overflow: hidden;
                border: 1px solid #009edc;
                 126px;
                z-index: 2;
                border-radius: 2px !important;
              }
              .filepond--browser {
                display: none;
              }
              .filepond--drop-label {
                opacity: 1 !important;
                transform: translate3d(0px, 0, 0) !important;
                visibility: visible !important;
                cursor: pointer;
                pointer-events: auto !important; // FIXME: allow multiple upload one by one
              }
              .filepond--drop-label label {
                line-height: 33px;
                padding: 0;
              }
              .filepond--drop-label label {
                cursor: pointer;
              }
              .filepond--drop-label label:active {
                color: white;
              }
              .filepond--file-action-button {
                cursor: pointer;
              }
              .filepond--drip, .filepond--drop-label, .filepond--panel {
                background: transparent !important;
                border-radious: 0;
                color: #009edc;
              }
              .filepond--drip, .filepond--panel-root {
                display: none;
              }
            `}
            </style>
          </div>
        );
      }
    }
    const mapStateToProps = state => ({
      token: state.user.token,
    });
    
    export default withAlert(connect(mapStateToProps, {})(FilepondUpload));

    页面中使用

    import FilepondUpload from './Filepond';
    
    <FilepondUpload
      uploadUrl={UPLOAD_URL}
      message="上传合同"
      fileType="contract"
      onUploaded={onUploaded}
      onError={this.repeatFileName}
      />
  • 相关阅读:
    Step by Step To Create a K8S Cluster
    Linux简单操作指令
    安装redis 最新版 redis-6.2.6
    GCC升级到11.2.0
    SQL开窗函数
    SQL 树形结构递归查询
    一文详解python的类方法,普通方法和静态方法
    _new_()与_init_()的区别
    关于Python的import机制原理
    【原创】android内存管理-hprof文件
  • 原文地址:https://www.cnblogs.com/susu8/p/9620311.html
Copyright © 2011-2022 走看看