繁体   English   中英

antd上传控件需要action函数,但我不需要

[英]action function is required with antd upload control, but I dont need it

我正在使用 ant 设计组件,并且我有一个上传输入: https ://ant.design/components/upload/

根据文档,需要对道具执行操作。

但是我不需要在上传时将文件发布到 url,我需要将整个 FORM 提交到 rest 端点(检查 handlesubmit 函数)

试图通过文档,我使用 handlechange 事件将文件添加到状态,但 STATUS 从未完成,因此永远不会命中该行。

我在这里想念什么?

import React, { Component } from 'react';
import { Input, Upload , Icon, message} from 'antd';
import Form from '../../components/uielements/form';
import Checkbox from '../../components/uielements/checkbox';
import Button from '../../components/uielements/button';
import Notification from '../../components/notification';
import { adalApiFetch } from '../../adalConfig';

const FormItem = Form.Item;

class RegisterTenantForm extends Component {
    constructor(props) {
        super(props);
        this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '', confirmDirty: false, loading: false, buttondisabled: true};
        this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
        this.handleChangeCertificatePassword = this.handleChangeCertificatePassword.bind(this);
        this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleupload = this.handleupload.bind(this);
        this.handleTenantIdValidation = this.handleTenantIdValidation.bind(this);
        this.handleTenantAdminUrl = this.handleTenantAdminUrl.bind(this);

    };

    handleChangeTenantUrl(event){
        this.setState({TenantUrl: event.target.value});
    }

    handleChangeCertificatePassword(event){
        this.setState({CertificatePassword: event.target.value});
    }

    handleChangeTenantId(event){
        this.setState({TenantId: event.target.value});
    }

    beforeUpload(file) {
        const isJPG = file.type === 'image/jpeg';
        if (!isJPG) {
          message.error('You can only upload JPG file!');
        }
    }

    handleupload(info){
        //let files = e.target.files;
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }

        if (info.file.status === 'done') {
            this.setState({ loading: false });
            this.setState({ 'selectedFile': info.file });
        }

    }

    handleTenantIdValidation(rule, value, callback){
        const form = this.props.form;
        const str = form.getFieldValue('tenantid');

        var re = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
        if (str && !str.match(re)) {
            this.setState({buttondisabled: true});
            callback('Tenant id is not correctly formated id');            
        } 
        else {
            this.setState({buttondisabled: false});
            callback();
        }
    }

    handleTenantAdminUrl(rule, value, callback){
        const form = this.props.form;
        const str = form.getFieldValue('tenantadminurl');

        var re = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/i;
        if (str && !str.match(re)) {
            this.setState({buttondisabled: true});
            callback('Tenant Url is not correctly formated id');
        } 
        else {
            this.setState({buttondisabled: false});
            callback();
        }
    }


    handleSubmit(e){
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                /*Notification(
                'success',
                'Received values of form',
                JSON.stringify(values)
                );*/

                let data = new FormData();
                //Append files to form data
                data.append("model", JSON.stringify({ "TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "CertificatePassword": this.state.CertificatePassword }));
                //data.append("model", {"TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "TenantPassword": this.state.TenantPassword });

                let files = this.state.selectedFile;
                for (let i = 0; i < files.length; i++) {
                  data.append("file", files[i], files[i].name);
                }

                const options = {
                  method: 'put',
                  body: data,
                  config: {
                    headers: {
                      'Content-Type': 'multipart/form-data'
                    }
                  }
                };

                adalApiFetch(fetch, "/Tenant", options)
                  .then(response => response.json())
                  .then(responseJson => {
                    if (!this.isCancelled) {
                      this.setState({ data: responseJson });
                    }
                  })
                  .catch(error => {
                    console.error(error);
                });
            }
        });      
    }



    render() {
        const { getFieldDecorator } = this.props.form;

        const formItemLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 6 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 14 },
        },
        };
        const tailFormItemLayout = {
        wrapperCol: {
            xs: {
            span: 24,
            offset: 0,
            },
            sm: {
            span: 14,
            offset: 6,
            },
        },
        };
        return (
            <Form onSubmit={this.handleSubmit}>
                <FormItem {...formItemLayout} label="Tenant Id" hasFeedback>
                {getFieldDecorator('tenantid', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant id',
                    },
                    {
                        validator: this.handleTenantIdValidation
                    }],
                })(<Input name="tenantid" id="tenantid" onChange={this.handleChangeTenantId}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate Password" hasFeedback>
                {getFieldDecorator('certificatepassword', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your password!',
                    }
                    ],
                })(<Input type="password" name="certificatepassword" id="certificatepassword" onChange={this.handleChangeCertificatePassword}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Tenant admin url" hasFeedback>
                {getFieldDecorator('tenantadminurl', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant admin url!',
                    },
                    {
                        validator: this.handleTenantAdminUrl
                    }],
                })(<Input name="tenantadminurl" id="tenantadminurl"  onChange={this.handleChangeTenantUrl} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate File">
                    <Upload  onChange={this.handleupload} beforeUpload={this.beforeUpload}>

                        <Button >
                            <Icon type="upload" /> Click to Upload
                        </Button>
                    </Upload>

                </FormItem>
                <FormItem {...tailFormItemLayout}>
                    <Button type="primary" htmlType="submit" disabled={this.state.buttondisabled}>
                        Register tenant
                    </Button>
                </FormItem>
            </Form>
        );
    }
}

const WrappedRegisterTenantForm = Form.create()(RegisterTenantForm);
export default WrappedRegisterTenantForm;

TL; 博士

使用模拟成功上传覆盖<Upload/>默认上传 AJAX 实现。

解决方案演示:
编辑 antd 上传组件作为文件选择器

完整答案

由于您自己将文件附加到formData ,您似乎试图将andt<Upload/>组件formData作文件选择器。 从未达到status === "done"的原因是因为文件并未真正上传到任何地方。
因此,您不需要像 OOB 那样自动上传文件。
您所需要的只是onChange将向您发送所选文件,您可以将其保存在状态树中的某个位置。
<Upload/>将另一个组件 ( rc-upload ) 渲染为处理实际 AJAX 上传的子组件。 您可以通过将customRequest道具传递给<Upload/> (将传递给rc-upload组件)来覆盖此行为。

您可以在这里看到哪些选项被传递给请求函数。 这是一个虚拟请求函数的实现:

const dummyRequest = ({ file, onSuccess }) => {
  setTimeout(() => {
    onSuccess("ok");
  }, 0);
};

然后你可以把它传递给<Upload customRequest={dummyRequest}/>
onChange仍然会被触发,但这次是"done"状态,因为虚拟请求函数模拟了一个成功上传的流程。

根据官方文档手动上传

beforeUpload返回false后手动上传文件。

beforeUpload(file) {
    const isJPG = file.type === 'image/jpeg';
    if (!isJPG) {
      message.error('You can only upload JPG file!');
    }
    return false;
}

扩展到@Quincy 的答案,您还可以在类似这样的组件上使用速记,

<Upload beforeUpload={() => false} />

Antd:使用 beforeUpload 上传唯一 jpeg 或 png 文件的最简单解决方案

<Upload
    fileList = {this.state.selectedLogo}
    customRequest = {customRequest}
    onChange = {this.onChangeLogo}
    showUploadList = {false}
    beforeUpload = {(file) => {
    const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
        if (!isJPG) {
            message.error('You can only upload JPG or PNG file!');
            return false;
        } else {
            return true;
        }
    }}
>

使用 Antd Dragger 进行类似的操作以在 React Native 中上传 csv,并能够使用 Ramy Ben Aroya 的答案使其正常工作:

const dummyRequest = async ({ file, onSuccess }) => {    
   setTimeout(() => {
      onSuccess("ok");
   }, 0);
 }


const fileProps = {
    name: 'file',
    multiple: true,
    customRequest: dummyRequest,
    onChange(info:any) {
      const { status } = info.file;
      if (status !== 'uploading') {
        console.log('uploading');
      }
      if (status === 'done') {
        getBase64(info.file.originFileObj, async (file: string) => {
          // handle data base or parse logic here using file
        });
       message.success(`${info.file.name} file uploaded successfully.`);
      } else if (status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
    onDrop(e) {
      console.log('Dropped files', e.dataTransfer.files);
    },
  };


<Dragger {...fileProps} style={{ maxHeight: "180px" }}>
  <p className="ant-upload-drag-icon">
    <InboxOutlined />
  </p>
  <p className="ant-upload-text">Click or drag file to this area to upload</p>
  <p className="ant-upload-hint">
     Supported file types: .csv 
  </p>
</Dragger>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM