美文网首页React
同步表单提交和异步表单提交以及提交前的预览

同步表单提交和异步表单提交以及提交前的预览

作者: CondorHero | 来源:发表于2019-08-23 00:15 被阅读1次
    一、传统表单提交(同步上传)

    先来复习一下 form 表单提交上传文件:

    <div>
        <form action="http://192.168.2.250/uppic" method = "post" encType = "multipart/form-data">
            <input type = "file" name = "file"/>
            <input type = "submit" />
        </form>
    </div>
    

    上传文件时表单必须加:encType = "multipart/form-data"。且提交方式也必须为
    post 请求。enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。

    默认地,表单数据会编码为 "application/x-www-form-urlencoded"。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。


    encType = "multipart/form-data

    这个方法提交的表单是同步的提交,因为提交完成还会进行页面跳转。体验不好故不用

    传统form表单提交.gif
    根据提交返回的结果,查看提交的图片:
    查看图片
    其中<input type = "file" name = "file" multiple/> multiple 表示多文件上传
    二、虚拟表单提交(异步上传)

    因为传文件只能表单上传,不能简单的放个 input 就上传文件,所以异步就是通过创建虚拟表单来提交数据。
    下面来进行创建:

    <input type = "file" ref = "file" multiple/>
    <button onClick = {()=>{
        // 点击提交创建虚拟表单
        let vform = new FormData();
        console.log(this.refs.file.files)//这个是上传文件的对象
        console.log(this.refs.file.files[0])
        // 追加文件
        vform.append('file',this.refs.file.files[0]);
    
        axios.post("http://192.168.2.250/uppic",vform).then(data=>{
            this.setState({
                filename : data.data.filename
            })
        });
    }}>提交</button>
    {/*图片预览*/}
    {   
        this.state.filename === "" ?
        null : <img src = {`http://192.168.2.250/uploads/${this.state.filename}`} />
    }
    

    console.log(this.refs.file.files[0])打印出的单个信息文件。


    单个文件详细信息

    axios 进行 post 请求的时候,文件格式这样的:

    axios.post('url, {
        dataName: 'data'
      })
    

    也可以对第一个括号里面的数据进行整合下写成下面这样推荐使用

    axios({
        method: 'post',
        url: 'http://192.168.2.250/uppic',
        data: vform,
        onUploadProgress: function (progressEvent) {
        // Do whatever you want with the native progress event
        }
    })
    

    axios 上传进度条提示格式代码:

    // `onUploadProgress` allows handling of progress events for uploads
      onUploadProgress: function (progressEvent) {
        // Do whatever you want with the native progress event
      }
    

    控制台打印出这个 progressEvent 形参,有两个很重要的参数,我们上传的进度就可以使用 loaded/total 来表示。



    现在来完成异步上传组件:

    import React, { Component } from 'react';
    import { Progress } from 'antd';
    import axios from "axios";
    export default class S1 extends Component {
        constructor(){
            super();
            this.state = {
                filename : "",
                progress : 0
            }
        }
        render() {
            return (
                <div>
                        <input type = "file" ref = "file" multiple/>
                        <button onClick = {()=>{
                            // 点击提交创建虚拟表单
                            let vform = new FormData();
                            // 追加文件
                            vform.append('file',this.refs.file.files[0]);
                            axios({
                                method: 'post',
                                url: '/api/uppic',
                                data: vform,
                                onUploadProgress: (progressEvent)=> {
                                    // ~~()取整
                                    this.setState({
                                        progress : ~~(progressEvent.loaded / progressEvent.total * 100)
                                    })
                                }
                            }).then(data=>{
                                this.setState({
                                    filename : data.data.filename
                                })
                            });
                        }}>提交</button>
                        {/*原型进度条*/}
                        <Progress type="circle" percent={this.state.progress} />
                        {/*上传完图片预览*/}
                        {   
                            this.state.filename === "" ?
                            null : <img style = {{"width":"150px"}} src = {`http://192.168.2.250/uploads/${this.state.filename}`} />
                        }
                </div>
            )
        }
    }
    

    把网速调慢实验效果如下:



    是不很别扭,图片应该是上传前预览呀。

    三、HTML5 把图片地址转成 base64

    HTML5 把图片地址转成 base64,HTML5 新特性,用来做图片上传前的预览。
    核心代码:

    <input type = "file" ref = "file" multiple onChange = {(e)=>{
        let file = e.target.files[0];
        // HTML的新特性可以把图片变成base64地址
        let fr = new FileReader();
        fr.readAsDataURL(file);
        fr.onload = (_e)=>{
            this.setState({
                base64 : _e.target.result
            })
        }
    }}/>
    
    上传前预览

    完整代码示例:

    import React, { Component } from 'react';
    import { Progress , Icon} from 'antd';
    import classnames from "classnames";
    import axios from "axios";
    export default class S1 extends Component {
        constructor(){
            super();
            this.state = {
                base64 : "",
                progress : 0
            }
        }
        render() {
            return (
                <div>   
                        <input type = "file" ref = "file" multiple onChange = {(e)=>{
                            let file = e.target.files[0];
                            // HTML的新特性可以把图片变成base64地址
                            let fr = new FileReader();
                            fr.readAsDataURL(file);
                            fr.onload = (_e)=>{
                                this.setState({
                                    base64 : _e.target.result
                                })
                            }
                        }}/>
                        <button onClick = {()=>{
                            // 点击提交创建虚拟表单
                            let vform = new FormData();
                            // 追加文件
                            vform.append('file',this.refs.file.files[0]);
                            axios({
                                method: 'post',
                                url: '/api/uppic',
                                data: vform,
                                onUploadProgress: (progressEvent)=> {
                                    // ~~()取整
                                    this.setState({
                                        progress : ~~(progressEvent.loaded / progressEvent.total * 100)
                                    })
                                }
                            }).then(data=>{
                                this.setState({
                                    filename : data.data.filename
                                })
                            });
                        }}>提交</button>
                        <div className = "img">
                            {/*上传之前图片预览*/}
                            <div>
                                {   
                                    this.state.base64 === "" ?
                                    null : <img style = {{"width":"150px"}} className = {classnames({
                                        img1:this.state.progress > 0 && this.state.progress < 100
                                    })} src = {this.state.base64} />
                                }
                            </div>
                            {/*原型进度条*/}
                            <div className = "img2">
                                <Progress className = {classnames({
                                        isHidden:this.state.progress <= 0 || this.state.progress >= 100
                                    })} type="circle" strokeColor = "primary" percent={this.state.progress} width = {150} />
                            </div>
                        </div>
                </div>
            )
        }
    }
    

    相关文章

      网友评论

        本文标题:同步表单提交和异步表单提交以及提交前的预览

        本文链接:https://www.haomeiwen.com/subject/wfkasctx.html