react图片上传,image.onload异步时图片上传闪烁的问题1

话不多说,代码攻心

import React,{Component} from 'react';
import {connect} from 'react-redux';
import { Upload, Icon, message } from 'antd';
function getBase64(img, callback) {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
}
function beforeUpload(file) {
    /*let isJPG = (file.type === 'image/png');//设置图片格式
    if (!isJPG) {
        message.error('You can only upload png/mp4 file!');
        return false;
    }*/  //没有accept好用
    let isLt50M = file.size / 1024 / 1024 < 50;//设置文件的大小
    if (!isLt50M) {
        message.error('图片大小因小于50MB!');
        return false;
    }
    return isLt5M; //&& show  isJPG &&
}
class Pay extends Component{
    constructor(){
        super();
        this.state = {}
    }
    state = {
        loading: false,
    };
    handleChange = (info) => {
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }
        if (info.file.status === 'done') {
            getBase64(info.file.originFileObj, imageUrl => {
                this.setState({
                    imageUrl: imageUrl,
                    loading: false,
                });
            });
        }
    };
    sizeConform = (imageUrl)=>{
        if(imageUrl){
            var image = new Image();
            image.onload =()=>{
                var width = image.width;
                var height = image.height;
                console.log(width, height);
                //var fileSize = image.fileSize;
                let a = ((9/16).toFixed(2));
                let b = ((16/9).toFixed(2));
                let c = (width / height).toFixed(2);
                //设置图片宽高比例   宽高比为9/16 或者16/9才行  数字可以自行设置
                if((c!== a)&&(c!==b)){
                    this.setState({imageUrl:null});
                    message.error("图片宽高比例错误")
                }
            };
            image.src = imageUrl;
        }
    };
    render(){
        const uploadButton = (
            <div>
                <Icon type={this.state.loading ? 'loading' : 'plus'} />
                <div className="ant-upload-text">Upload</div>
            </div>
        );
        const imageUrl = this.state.imageUrl;
        this.sizeConform(imageUrl);    
        return (
            <Upload  
                name="avatar"
                listType="picture-card"
                className="avatar-uploader"
                showUploadList={false}
                action="//jsonplaceholder.typicode.com/posts/"
                beforeUpload={beforeUpload}
                onChange={this.handleChange}
                accept=".png,.mp4" 
            >
                {imageUrl ? <div className="imgBox"><img src={imageUrl} alt="avatar" className="ant-upload"/></div> : uploadButton}
            </Upload>
        );
    }
}
export default connect(null,null)(Pay);
//Upload里的属性设置 详见:https://ant.design/components/upload-cn/

绕了一些坑,想要实现上传限制,需要获取到图片路径。
如果直接在beforeUpload里面设置拦截,由于异步的问题会造成拦截失败,图片照样上传
目前的解决方法,我是放到了组件内部实现,在组件将要渲染的时候拦截,也就是
render里用的this.sizeConform(imageUrl); 这个方法;拿到图片后验证宽高比例,比例不对则拦截
上面的是出版,有些小bug
但是想在beforeUpload的时候就做到这步,下面是三四个小时之后的成果,感谢小伙伴的支援,才出的成果

import React,{Component} from 'react';
import {connect} from 'react-redux';
import { Upload, Icon, message } from 'antd';
import "./Pay.less";

class Pay extends Component{
    constructor(){
        super();
        this.state = {loading: false}
    }
    getBase64=(img, callback)=>{
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    };
    beforeUpload=(file)=>{
        let imgUrl = '';
        this.getBase64(file,imageUrl => {
            imgUrl=imageUrl;
            let that = this;
            if(imgUrl) {
                var image = new Image();
                var myPromise = () =>{
                    return new Promise(function(resolve,reject){
                        image.onload = () => {
                            var width = image.width;
                            var height = image.height;
                            //var fileSize = image.fileSize;
                            let a = ((9 / 16).toFixed(2));
                            let b = ((16 / 9).toFixed(2));
                            let c = (width / height).toFixed(2);
                            if ((c !== a) && (c !== b)) {
                                message.error("图片宽高比例错误");
                                resolve('null');
                            }else{
                                reject(imgUrl);
                            }
                        };
                        image.src = imgUrl;
                    })
                }
            }
            myPromise().then(null,function(message){
                that.setState({imageUrl: message});
            })
        });//通过Promise的链式写法,在验证完成之后再设置state里的状态,根据myPromise的执行结果动态赋值
        //要是你们有更好的解决方法,欢迎探讨
        let isLt50M = file.size / 1024 / 1024 < 50;
        if (!isLt50M) {
            message.error('图片大小因小于50MB!');
            this.setState({imageUrl: null});
        }
    };
    handleChange = (info) => {
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }
        if (info.file.status === 'done') {
            // Get this url from response in real world.
            this.getBase64(info.file.originFileObj, imageUrl => {
                this.setState({
                    loading: false,
                });
            });
        }
    };
    render(){
        const uploadButton = (
            <div>
                <Icon type={this.state.loading ? 'loading' : 'plus'} />
                <div className="ant-upload-text">Upload</div>
            </div>
        );
        const {imageUrl} = this.state;
        return (
            <Upload
                name="avatar"
                listType="picture-card"
                className="avatar-uploader"
                showUploadList={false}
                action="//jsonplaceholder.typicode.com/posts/"
                beforeUpload={this.beforeUpload}
                onChange={this.handleChange}
                accept=".png,.mp4"
            >
                {
                    imageUrl ?<div className="imgBox"><img src={imageUrl} alt="avatar" className="ant-upload"/></div>:uploadButton
                }
            </Upload>
        );
    }
}
export default connect(null,null)(Pay);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值