react中基于腾讯云cos上传图片组件
- 效果示例图
- 上传图片组件imageUpload
- components/imageUpload/index.jsx
- components/imageUpload/upload.scss
- 使用组件
效果示例图
上传图片组件imageUpload
npm install cos-js-sdk-v5 -S
components/imageUpload/index.jsx
import "./upload.scss";
import uploadImg from "../../assets/images/icon_upload_default.png";
import { useEffect, useState } from "react";
const COS = require("cos-js-sdk-v5");
const Bucket = "yugioh-xxx";
const Region = "ap-shanghai";
//创建一个 COS SDK 实例
const cos = new COS({
SecretId: "xxxxx",
SecretKey: "xxxx",
});
//图片item
function ImageItem(props) {
let item = props.item;
// 删除图片
function deleteImageHandle(params) {
props.click(params);
}
return (
<li className="image-item" key={item.uid}>
<img className="imgage-icon" alt={item.name} src={item.url} />
<div
className="imgage-delete"
onClick={() => {
deleteImageHandle(item);
}}
>
删除
</div>
</li>
);
}
function UploadImages(props) {
//文件类型, 例如['png', 'jpg', 'jpeg']
let [fileType, setFileType] = useState(["png", "jpg", "jpeg"]);
//数量限制
let [limit, setLimit] = useState(5);
//大小限制 (MB)
let [fileSize, setFileSize] = useState(20);
let [fileList, setFileList] = useState([]);
/**
* 上传前校检格式和大小
* **/
function verifyUploadFile(file) {
// 校检文件类型
if (fileType) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
const isTypeOk = fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
if (!isTypeOk) {
console.log(`文件格式不正确, 请上传${fileType.join("/")}格式文件!`);
return false;
}
}
// 校检文件大小
if (fileSize) {
const isLt = file.size / 1024 / 1024 < fileSize;
if (!isLt) {
console.log(`上传文件大小不能超过 ${fileSize} MB!`);
return false;
}
}
return true;
}
/**
* 上传图片到腾讯云
* **/
function uploadFileToTencentClound(file) {
return new Promise((resolve) => {
cos.putObject(
{
Bucket: Bucket /* 存储桶 */,
Region: Region /* 存储桶所在地域,必须字段 */,
Key: "fileImage/" + file.name /* 文件名 */,
StorageClass: "STANDARD", // 上传模式, 标准模式
Body: file, // 上传文件对象
onProgress: function (info) {
console.log("[cos.postObject-seccess]", JSON.stringify(info));
},
},
function (err, data) {
console.log("[cos.postObject-err]", err || data);
resolve(data.Location);
}
);
});
}
/**
* 监听input[type=file]是否变化
* **/
function uploadFileHandle(e) {
let files = e.target.files;
if (files.length > 0) {
if (fileList.length + files.length <= limit) {
for (let i = 0; i < files.length; i++) {
if (verifyUploadFile(files[i])) {
uploadFileToTencentClound(files[i]).then((response) => {
fileList.push({
uid: files[i].lastModified,
name: files[i].name,
url: "https://" + response,
});
setFileList([...fileList]);
});
}
}
} else {
console.log(`上传文件数量不能超过 ${limit} 个!`);
}
}
}
//删除图片
function deleteHandle(e) {
setFileList((current) => current.filter((file) => file.uid !== e.uid));
}
useEffect(() => {
if (props.fileType) {
setFileType(props.fileType);
}
if (props.limit) {
setLimit(props.limit);
}
if (props.fileSize) {
setFileSize(props.fileSize);
}
console.log("[fileList]", fileList);
props.upload(fileList);
}, [props, fileList]);
return (
<>
{fileList.length < limit ? (
<div className="uploadImage">
<label className="label" htmlFor="uploadFile">
<img alt="" className="upload-icon" src={uploadImg} />
<div className="upload-text">上传图片</div>
</label>
<input
type="file"
name="uploadFile"
id="uploadFile"
multiple
onChange={uploadFileHandle}
/>
</div>
) : (
<></>
)}
{/* 图片列表 */}
<ul className="imageList">
{fileList.map((item) => (
<ImageItem key={item.uid} item={item} click={deleteHandle} />
))}
</ul>
</>
);
}
export default UploadImages;
components/imageUpload/upload.scss
.uploadImage {
border: 1px solid #dcdcdc;
border-radius: 4px;
width: 100px;
height: 100px;
position: relative;
overflow: hidden;
.label {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
cursor: pointer;
.upload-icon {
width: 54px;
height: 32px;
}
.upload-text {
margin-top: 6px;
}
}
input[name="uploadFile"] {
opacity: 0;
}
}
.imgStyle {
width: 200px;
height: auto;
margin-top: 6px;
}
.imageList {
width: 100%;
display: flex;
flex-direction: column;
.image-item {
border: 1px solid #dcdcdc;
border-radius: 4px;
display: flex;
flex-direction: row;
position: relative;
margin: 4px 4px;
padding: 2px 2px;
.imgage-icon {
width: auto;
height: 100px;
}
.imgage-delete {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 20px;
font-size: 16px;
color: #ff0000;
}
}
.image-item:hover {
border: 1px solid #ff0000;
cursor: pointer;
}
}
使用组件
import { useEffect } from "react";
//上传图片
import ImageUpload from "../../components/imageUpload";
function Upload() {
function uploadHandle(params) {
console.log("[0]", params);
}
useEffect(() => {
console.log("[upload]");
}, []);
return (
<>
<div>选择图片</div>
<ImageUpload upload={uploadHandle} />
</>
);
}
export default Upload;