之前在网上也找不到Web具体实行OBS上传的代码,自己试着写了一下,感觉也还行,仅供参考,话不多说上代码
import * as React from "react";
import { Upload, Button, Icon, message, Modal } from "antd";
import "./uploads.less";
export default class UploadData extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = {
loading: false,
uploadData: {},
fileList: [],
};
}
componentDidMount() {
}
// 上传前的检验,指定上传类型,判断大小等
beforeUpload = async (file, fileList) => {
await this.getFileData();
return new Promise((resolve, reject) => {
if (file?.size > 1024 * 1024 * 1024) {
message.error("请上传1G以内的文件");
return reject(false);
}
return resolve(true);
});
};
getFileType = (obj) => {
let fileType = "Other";
let mimeTypes = obj.type && obj.type.split("/")[0];
if (mimeTypes === "image" || mimeTypes === 'Pic') {
fileType = "Pic";
} else if (mimeTypes === "video") {
fileType = "Video";
} else if (mimeTypes === "audio") {
fileType = "Audio";
}
return fileType;
};
// 重点-上传方法
upload = (data) => {
const obsClient = new ObsClient({
access_key_id: ‘ your access_key_id’,
secret_access_key: ‘your secret_access_key ’,
server: ' your OBS Endpoint', //捅配置里面获取
});
// 设置表单参数
var formParams = {
// 设置对象访问权限为公共读
'x-obs-acl': obsClient.enums.AclPublicRead,
// 设置对象MIME类型
'content-type': 'text/plain'
};
// 设置表单上传请求有效期,单位:秒
var expires = 3600;
var res = obsClient.createPostSignatureSync({ Expires: expires, FormParams: formParams });
obsClient.putObject({
Bucket: ' your Bucket', // 桶名称
Key: `具体上传文件夹/${data.file.name}`, // 桶 内对象文件存储地址 文件夹名称 +上传文件名
SourceFile: data.file,
Policy: res.Policy, // 策略
Signature: res.Signature, //签名
expires
}, function (err, result) {
if (err) {
//此处上传失败后 可以调 data.onError 方法报错,upload 报错红色条,也可以在data 里面找到对应的方法改动
console.error('Error-->' + err);
data.onError()
} else {
//此处上传成功后 可以调 data.onSuccess() 更改文件上传对象的状态
console.log('Status-->' + result.data);
data.onSuccess()
}
})
}
// 整理数据,并传到表单
sumbitData = () => {
const { fileList } = this.state;
const list = fileList.map((item) => {
let obj = {
fileType: this.getFileType(item),
fileName: item.name,
uri: item.response && item.response.url,
previewUri: item.response && item.response.previewUrl,
size: Number(item.size),
ext: item.name && item.name.split(".")[1],
};
return obj;
});
this.props.onChange(list);
};
render() {
const { singleFile, btnType, btnTitle, unIncon, value, remark, listType, isOnlyFile, accept, showUploadList } = this.props;
let uploadType = listType || "text";
let acceptType = accept || (listType === "picture-card" ? "image/*" : null);
let showUploads = true;
if (showUploadList === null || showUploadList === undefined) {
showUploads = true;
} else if (!showUploadList) {
showUploads = false;
}
const uploadProps: any = {
name: "file",
beforeUpload: this.beforeUpload,
multiple: !singleFile, // 默认true
listType: uploadType,
showUploadList: showUploads,
customRequest: this.upload, // 使用antd upload 重新定义上传方法
fileList: this.state.fileList,
onChange: (info) => {
if (info.file.status === "done") {
this.sumbitData();
} else if (info.file.status === "error") {
message.error(`${info.file.name} 上传失败.`);
} else if (info.file.status === "removed") {
this.setState({ fileList: info.fileList }, () => {
this.sumbitData();
});
}
if (isOnlyFile) {
this.setState({
fileList: [{
...info.file,
}]
});
} else {
let infoData = info
this.setState({ fileList: infoData.fileList });
}
},
};
return (
<div className="upload">
<Upload {...uploadProps} accept={acceptType}>
{uploadType === "text" && (
<div>
<Button type={btnType || "default"}>
{unIncon ? null : <Icon type="upload" />}
{btnTitle || "上传文件"}
</Button>
{remark && <span style={{ marginLeft: 15, marginTop: 5, fontSize: 12, color: "#999" }}>{remark || ""}</span>}
</div>
)}
{uploadType === "picture-card" && (
<div>
<Icon type={this.state.loading ? "loading" : "plus"} />
<div style={{ fontSize: "12px" }}>{btnTitle || "上传图片"}</div>
</div>
)}
</Upload>
</div>
);
}
}
less 样式
.upload {
.file-item {
display: flex;
align-items: center;
height: 32px;
font-size: 14px;
}
.img-wrap {
display: flex;
flex-direction: row;
align-items: center;
.img-item {
height: 64px;
width: 64px;
margin-right: 10px;
}
}
.file-name {
margin-left: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 15px;
}
.file-del {
margin-left: auto;
}
.delete {
cursor: pointer;
&:hover {
color: #099aff;
}
}
}
关于预览
因为考虑到安全问题,目前OBS内不支持浏览器直接预览。根据官方给的方法,就是要配置域名链接到桶内,开放公开权限才能使用域名来直接访问桶内上传的文件或者图片
所以浏览器预览上传OBS的图片或者文件只能使用域名来访问 。
示例: https://ceshiOBS.preview.cn/ceshiwenjian/${info.file.name} //域名是要配置证书的,没有在证书就使用http 。
如果有那种弹窗需要预览的,就要把这种URL 传入,才能访问到图片或者文件。