Antd上传文件实践

本文介绍如何使用Ant Design的Form组件结合React实现表单数据与头像图片的联合上传,通过FormData处理多类型数据,并在后端利用Express和Multiparty解析请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版本:
"react": "^16.13.1"
"antd": "^4.0.4

用antd的Form组件做了一个注册表单,注册的同时上传一个头像文件,当点击注册,所有数据包括头像一起传给后端处理。

 

需要解决两个问题:

1. 表单字段数据和图片数据要一起传给后端。

2. 后端分别处理字段数据和图片数据,图片名保存到mongodb数据库,图片保存到本地。

注:这里没有写密码校检逻辑,主要关注图片如何被上传。

注册组件

import React, { Component } from 'react';
import axios from 'axios';
import { Input, Button, Form, Upload } from 'antd';
import { UploadOutlined } from '@ant-design/icons';

class Regist extends Component {
  
  constructor(props) {
      super(props);
      this.formRef = React.createRef();
      this.regist = this.regist.bind(this);
  }
  
  regist() {
    const { username, password, header } = this.formRef.current.getFieldsValue();
    let data = new FormData();
    data.append('username', username);
    data.append('psw', password);
    /* header.file是一个File对象
       数据类似如下:
       {
         fieldName: 'header',
         originalFilename: 'head.jpg',
         path: 'public\\images\\jWwK3Rb04uhiSygh5UkIwcqj.jpg',
         headers: [Object],
         size: 38302
       }
     */
    data.append('header', header.file);
    let that = this;
    axios.post( '/api/regist', data)
    .then( function (res) {
      if ( res.data === "注册成功" ) {
        that.props.history.push('/');
      } else {
        alert(res.data);
      }
    });
  }
  
  render() {
    const layout = {
      labelCol: { offset: 6, span: 4, },
      wrapperCol: { span: 8 }
    };
    const tailLayout = {
      wrapperCol: { offset: 10, span: 14 }
    };
    return (
      <Form
        {...layout}
        ref={this.formRef}
        name="basic"
      >
        <Form.Item
          label="Username"
          name="username"
          rules={[
            {
              required: true,
              message: 'Please input your username!',
            },
          ]}
        >
          <Input />
        </Form.Item>      
        <Form.Item
          label="Password"
          name="password"
          rules={[
            {
              required: true,
              message: 'Please input your password!',
            },
          ]}
        >
          <Input.Password />
        </Form.Item>  
        <Form.Item
          label="Again"
          name="again"
          rules={[
            {
              required: true,
              message: 'Please input your password again!',
            },
          ]}
        >
          <Input.Password />
        </Form.Item>
        <Form.Item
          name="header"
          label="Header"
          valuePropName="logoFile"
          extra="上传的图片小于2M"
        >
          <Upload
            name="logo"
            // 解除Upload组件的默认行为
            beforeUpload={(file, fileList)=>false}
            listType="picture"
          >
            <Button>
              <UploadOutlined /> 上传头像
            </Button>
          </Upload>
        </Form.Item>
        <Form.Item {...tailLayout}>
          <Button type="primary" htmlType="submit" onClick={this.regist}>注册</Button>
          <Button onClick={()=>this.props.history.push('/')}>返回</Button>
        </Form.Item>
      </Form>
    );
  }
  
}

export default Regist;

后端处理

后端使用express框架,使用multiparty来处理post过来的数据。

router.post( '/api/regist', function(req, res, next) {
  // uploadDir上传文件路径
  let form = new multiparty.Form( {uploadDir: './public/images/'} );
  form.parse( req, function(err, fields, files){
    /* 
     fields的数据类似如:
      { username: [ 'jay' ], psw: [ 'jay' ] }
     files的数据类似如:
      {
        header: [
          {
            fieldName: 'header',
            originalFilename: 'head.jpg',
            path: 'public\\images\\bDfITS0MZUtVK8eda122lkln.jpg',
            headers: [Object],
            size: 38302
          }
        ]
      }
     */
    UserModel.find(
      { usernmae: fields.username[0] },
      function(err, docs) {
        if ( docs.length > 0 ) {
          console.log(docs);
          res.send('该用户名已经被占用,请重新输入用户名。');
          return;
        }
        let user = new UserModel();
        user.username = fields.username[0];
        user.psw = md5(fields.psw[0]);
        let path = files.header[0].path;
        // 截取文件名部分
        user.header = path.substr( path.lastIndexOf('\\') + 1 );
        user.save( function(err){
          if (err) {
            res.send('注册失败');
          } else {
            res.send('注册成功');
          }
        });
      }
    );
  });
});

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值