react:react-cropper插件,實現圖片裁剪upload上傳功能

因業務需求,需要用戶自定義個人頭像(圖片剪切上傳);調研了之後,決定使用react-cropper插件來實現頭像上傳功能!

react-cropper插件還是很全面不錯的, 滿足了功能的需要。

步驟實現:

1、安裝

      npm install --save react-cropper

2、文件引入

      import "cropperjs/dist/cropper.css"

      import Cropper from 'react-cropper'

3、render結構

render() {
    return (
        <div>
            <div>
                <div>
                    <Cropper 
                        style={{ width: "300", height: "200" }}
                        aspectRatio={1} 
                        preview=".uploadCrop"
                        guides={false} 
                        src={this.state.src}
                        ref={cropper => {this.cropper = cropper}}
                    />
                </div>
                <div>
                    <div className="uploadCrop" />
                </div>
            </div>
            <div>
                <input type="file" title="" accept="image/*" onChange={this.onChange} />
                <input type="button" value="上傳" onClick={() => this.uploadImg()} />
            </div>
        </div>
    )
}

備註: [1]、uploadCrop 指類名爲 uploadCrop 的div作爲預覽窗口(如果無法預覽, 需要添加樣式:overflow:hidden)

            [2]、src : 目標圖片url

            [3]、屬性 accept:表示可以上傳的文件類型,image表示圖片,*表示所有的支持格式。(不建議使用accept屬性,可使用JS驗證或服務端驗證)

4、核心代碼

     [1]、當input type=file 選取文件時, 對文件的類型和大小進行驗證;

     [2]、將 files[0] 的值傳進來,讀取,讀取完成之後設置src,給下一步使用;

const FILE_TYPES = ["image/jpg", "image/png", "image/jpeg", "image/bmp"];

constructor(props) {
    super(props);
    this.state = {
        src: null,
        fileName: "newFile.jpeg"
    }
    this.onChange = this.onChange.bind(this);
}

onChange(e) {
    e.preventDefault();
    let files;
    if(e.dataTransfer) {
        files = e.dataTransfer.files;
    } else if(e.target) {
        files = e.target.files;
    }

    if(files.length > 0){
        // 驗證 files[0] 信息的文件大小
        const fileMaxSize = 1024;
        let fileSize = files[0].size/1024;
        if(fileSize > fileMaxSize){
            alert("文件不能大於1M!");
            return false;
        } else if(fileSize <= 0) {
            alert("文件不能爲0");
            return false;
        }

        // 驗證 files 信息的文件類型
        const fileType = file.type;
        if(!FILE_TYPES.includes(fileType)) {
            alert("不接受此文件類型");
            return false;
        }        
        
        const reader = new FileReader();
        reader.onload = () => {
            this.setState({
                src: reader.result
            })
        }
        reader.readAsDataURL(files);

    } else {
        if(this.state.src === null) {
            alert("請選擇文件");
        }
        return false;
    }
}

5、提交裁剪好的圖片(form形式提交)

uploadImg() {
    if(this.state.src === null) {
        alert("請選擇圖片");
        return false;
    }

    const croppedCanvas = this.cropper.getCroppedCanvas({
        minWidth: 200,
        minHeight: 200,
        width: 200,
        height: 200,
        maxWidth: 200,
        maxHeight: 200
    });

    if(typeof croppedCanvas === "undefined") {
        return;
    }
    croppedCanvas.toBlob(async blob => {
        // 圖片name添加到blob對象裏
        blob.name = this.state.fileName;
        // 創建提交表單數據對象
        const filedata = new FormData();
        // 添加要上傳的文件
        filedata.append('file', blob, blob.name);
        
        try {
            // 接口
            let res = await upload(filedata, token);
            if(res.errCode === 0) {
                // 上傳成功
            } else {
                // 上傳失敗
            }
        } catch(err) {
            console.log(err);
            
        }
    }, "image/jpeg")
}

6、效果展示(至此,功能實現)

     

重要補充:

在第5步步驟中, 所使用到的upload方法, react中寫的時候需要注意了, 不是傳統的post能解決的,因爲接收參數時,一個參數是body接收的form對象,一個是headers接收的token;代碼如下:

upload(file, token) {
    return fetch("url地址", {
        body: file,
        credentials: 'include',
        headers: {
            'token': token
        },
        method: 'POST'
    })
    .then(response => response.json())
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章