因業務需求,需要用戶自定義個人頭像(圖片剪切上傳);調研了之後,決定使用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())
}