裁剪图片并上传到阿里云的oss服务器上

版权声明:~~~~~~官话之未经允许不能转载~~~~~~ https://blog.csdn.net/qq_41653587/article/details/89213203

在react项目整体利用umijs脚手架搭建,可以进umijs官网跟着步骤一步步来,然后在src目录下新建自己的js组件,样式文件这里没有,想要什么效果,自己可以新建一个空的样式文件进行编写,再测试一下代码即可。其实难点没有,都是别人写好的东东,要学的就是怎么套用,功能是怎么实现的,在实现功能的过程中可以尝试阅读组件的实现方式,学习他人的编码习惯,不断让自己养成编写规范代码的好习惯!!!

先说裁剪

  1. 下载react-cropper
npm install --save react-cropper 
  1. 需要导入的包
import React, {Component} from 'react';   
import {Upload, Icon, Button, Modal} from 'antd';            //利用Ant+Design中的Upload
import Cropper from 'react-cropper';                         //在导入之前,确保已经安装了react-cropper
import 'cropperjs/dist/cropper.css';                         //cropper样式文件
import './infoManage.scss'                                   //当前组件的样式文件
import userImg from '../../../assets/images/userCenter/head-img.png'             //我的页面中需要用到的图片资源
  1. render部分
  render() {
        const imageUrl = this.state.imageUrl;         //涉及到的state中的初始化变量在第4点中有定义
        return (
            <div className="user-img">
                <div className="img-content-top">
                    <div className="img-content-left">
                        <div className="choose-img">
                            {/*<input type="file" className="myFileUpload" onChange={this.handleFileChange}/>*/}
                            {
                                this.state.userImg?
                                    <img className="oldUserImg" src={userImg} alt="用户头像"/>
                                    :
                                    //关于Cropper组件的使用我没有很熟练,只是需要什么效果就添加相应的参数进行配置  [参数解释](https://blog.csdn.net/qq_38048243/article/details/82013533)
                                    <Cropper
                                        src={this.state.srcCropper} //图片路径,即是base64的值,在Upload上传的时候获取到的
                                        ref="cropper"
                                        style={{height: 400}}       //react中样式需要写在双大括号中
                                        preview='.cropper-preview'    //指定类名为.cropper-preview的div作为预览的窗口
                                        className="company-logo-cropper"
                                        viewMode={1}        //定义cropper的视图模式,1代表限制裁剪框不超过画布大小
                                        zoomable={false} //是否允许放大图像,默认为true
                                        aspectRatio={50 / 50} //image的纵横比,即裁剪框的固定宽高比,默认情况下是自由比率
                                        guides={true} //显示在裁剪框上方的虚线   默认为true
                                        background={false} //显示容器的网格背景,即是否显示背景的马赛克,默认为true
                                        rotatable={false} //是否允许旋转图像   默认为true
                                        crop={this._crop.bind(this)}
                                        key="1"
                                    >
                                    </Cropper>
                            }



                        </div>
                        {/*<p className="img-request">只支持JPG、PNG、GIF,大小不超过5M</p>*/}
                    </div>
                    <div className="img-content-right">
                        <span className="pre-show">预览</span>
                        <div className="img-big">

                            {imageUrl ? <img src={imageUrl} alt="大图" className="upload-big"/> : <i/>}
                            <span>100*100px</span>
                        </div>
                        <div className="img-middle">
                            {imageUrl ? <img src={imageUrl} alt="中图" className="upload-middle"/> : <i/>}
                            <span>50*50px</span>
                        </div>
                        <div className="img-small">
                            {imageUrl ? <img src={imageUrl} alt="小图" className="upload-small"/> : <i/>}
                            <span>30*30px</span>
                        </div>
                    </div>
                </div>

                <div className="img-content-bottom">
                //ant design中的Upload组件,详情可查看官网详细代码
                    <Upload
                        name="avatar"
                        listType="picture-card"
                        className="avatar-uploader myFileUpload"
                        showUploadList={false}
                        action="//jsonplaceholder.typicode.com/posts/"
                        beforeUpload={this.beforeUpload}      //上传之前
                        onChange={this.handleChange}         
                    >
                        <a className="greenButton">+选择图片</a>
                        {/*{this.state.imageUrl ? <img src={this.state.imageUrl} alt="avatar" /> : uploadButton}*/}
                    </Upload>
                    <button className="sure" onClick={this.submitImg}>确定</button>
                    <button className="cancel" onClick={this.cancelImg}>取消</button>
                    <button className="lj-save-img" onClick={this.saveImg}>保存</button>

                </div>
            </div>


        );
    }
  1. 涉及到的方法,因为是react-cropper + ant design一起实现,所以关于上传文件部分的方法直接从ant design官网拷贝就可以了;而跟cropper相关的方法中只需要做相应的state修改就可以实现,关于cropper中参数的解释:
    cropper参数解释看过来
function getBase64(img, callback) {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
}

class UserImg extends Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: false,
            visImg: false,
            imageUrl: "",
            temporaryUrl: "",
            userImg: true,        
        }
    }
//Upload上传之前的函数
    beforeUpload = (file) => {

        const isLt5M = file.size / 1024 / 1024 < 5;
        if (!isLt5M) { //添加文件限制
            console.log('文件大小');
            return false;
        }
        const isJPG = file.type === 'image/jpeg';
        const isPNG = file.type === 'image/png';
        const isGIF = file.type === 'image/gif';
        const isIMG = !isJPG || !isPNG || !isGIF;
        if (!isIMG) {
            console.log('格式不正确');
            return false;
        }
        var reader = new FileReader();
        reader.readAsDataURL(file); //开始读取文件
        // 因为读取文件需要时间,所以要在回调函数中使用读取的结果
        reader.onload = (e) => {
            this.setState({
                srcCropper: e.target.result, //cropper的图片路径
                selectImgName: file.name, //文件名称
                selectImgSize: (file.size / 1024 / 1024), //文件大小
                selectImgSuffix: file.type.split("/")[1], //文件类型
                visImg: true, //打开控制裁剪弹窗的变量,为true即弹窗
                userImg:false
            })
        }
        return false;
    };
    submitImg = () => {
        console.log('提交');
    };
    handleChange = (info) => {
        console.log(info.file);
        if (info.file.status === 'uploading') {
            this.setState({loading: true});
            return;
        }
        if (info.file.status === 'done') {
            console.log('执行upload成功');
            // Get this url from response in real world.
            getBase64(info.file.originFileObj, imageUrl => this.setState({
                imageUrl,
                srcCropper: imageUrl,
                loading: false,
                visImg: true,
            }));
        }
    };

    // 保存图片
    //点击保存的函数,需要在这里进行压缩
    saveImg = () => {
        const temporaryUrl = this.state.temporaryUrl;
        this.setState({
            imageUrl: temporaryUrl,
            visImg: false,
        })
    };

    _crop() {
        // image in dataUrl
        const cropperUrl = this.refs.cropper.getCroppedCanvas().toDataURL();
        // console.log(this.refs.cropper.getCroppedCanvas().toDataURL());
        this.setState({
            temporaryUrl: cropperUrl,
            // imageUrl: cropperUrl,
        })

    };
    //点击取消按钮的时候“取消修改当前图片,恢复用户原先使用的图片”
    cancelImg = ()=>{
        this.setState({
            userImg:true,
            imageUrl:''
        })
    }
//-----------------------------------------将上边的render方法拷贝在此处--------------------------------------------
   
}

export default UserImg;

再来上传

【利用Ant Design以及OSS实现图片上传(这里我只简单描述一下单图片上传的步骤)】

  1. 下载依赖
npm i ali-oss          # oss功能封装
npm i moment           # 为每一天的上传文件创建目录
  1. 下载好以后在js组件顶部引入即可

import OSS from 'ali-oss';
import moment from 'moment';
  1. 在紧跟着import之后将以下代码附上
  • 将base64位的图转为blob,
function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
}
  • 个人理解该变量是接收一个跟阿里云oss服务器参数相关的返回值
const client = self => {
    const { token } = self.state;
    return new OSS({
        accessKeyId: token.access_key_id,
        accessKeySecret: token.access_key_secret,
        region: token.region, //
        bucket: token.OSS_BUCKET, //
    });
};
  • 图片上传最好重新命名,其实很好理解,就是为了防止图片上传后命名冲突的问题
const uploadPath = (path, file) =>
    // 上传文件的路径,使用日期命名文件目录
    `${moment().format('YYYYMMDD')}/${file.name.split('.')[0]}-${file.uid}.${file.name.split('.')[1]}`;


  • 将图片上传到oss服务器
//path对应oss的存储路径位置;
//file对应本地要上传的图片信息,包括名称,路径等
const UploadToOss = (self, path, file) => {
    const url = uploadPath(path, file);
    return new Promise((resolve, reject) => {
        client(self)
            .multipartUpload(url, file)
            .then(data => {
                resolve(data);
            })
            .catch(error => {
                reject(error);
            });
    });
};
  1. 将之前写的beforeUpload方法中的reader.onload方法中内容替换成以下代码
// 使用ossupload覆盖默认的上传方法,其中data中有本地file在oss服务器上的存储地址即data.res.requestUrls。
UploadToOss(this, '上传路径oss配置信息', file).then(data => {
    this.setState({
    //temporaryUrl是我的页面中需要用到的一个state,你可以换成你所要需要的state变量
    temporaryUrl: data.res.requestUrls,
    srcCropper: e.target.result, //cropper的图片路径
    selectImgName: file.name, //文件名称
    selectImgSize: (file.size / 1024 / 1024), //文件大小
    selectImgSuffix: file.type.split('/')[1], //文件类型
    visImg: true, //打开控制裁剪弹窗的变量,为true即弹窗
    userImg: false,
	});
});
        
  1. 如果是裁剪后的图片要上传,可以添加以下方法
//这里方法名随自己定
1.imgUrl参数代表裁剪后的图片,现在这个图片的格式还是base64位格式的
2.因为上传阿里云需要给图片重命名,而重命名需要图片的name以及uid,那么不妨将原图片file传进来,给裁剪后的图片添加需要的属性
upcooper = (imgurl, file) => {
        imgurl.name = file.name;
        imgurl.uid = file.uid;

        var reader = new FileReader();
        reader.readAsDataURL(imgurl); //开始读取文件
        //因为读取文件需要时间,所以要在回调函数中使用读取的结果
        
        reader.onload = (e) => {    
            // 使用ossupload覆盖默认的上传方法
            UploadToOss(this, '上传路径oss配置信息', imgurl).then(data => {
                //截取的图片
                let cooperimg = data.res.requestUrls[0].split('?')[0];

                this.setState({
                    temporaryUrl: cooperimg,
                });
                const { dispatch } = this.props;
                //调用models的js文件中的异步方法infoImageData,在这个方法中会向后台接口发请求
                dispatch({
                    type: 'userCenter/infoImageData',
                    // payload: { uid: '2',url:this.state.temporaryUrl},
                    payload: { uid: '2', url: this.state.temporaryUrl },
                }).then(() => {
                    console.log(this.props.infoImageData);
                    this.setState({
                        userImg: true,
                    });

                });
            });
        };
        return false;
    };

猜你喜欢

转载自blog.csdn.net/qq_41653587/article/details/89213203