由于视频文件太大,不适合通过自己服务器中转一层,还是在前端直接传到七牛云合理。
文档
- 七牛云 Go SDK 文档,参考上传凭证的生成:https://developer.qiniu.com/kodo/sdk/go
- 七牛云 JS SDK 文档,参考其自定义文件名:https://developer.qiniu.com/kodo/1283/javascript
关于 token
token 上传凭证。
- 作用:客户端(移动端或者Web端)上传文件的时候,需要从客户自己的业务服务器获取上传凭证
- 有效期:默认情况下,在不指定上传凭证的有效时间情况下,默认有效期为1个小时。也可以自行指定上传凭证的有效期
- 是否有调用频率限制:无。因为最简单的上传凭证只需要AccessKey,SecretKey和Bucket就可以,不需要与七牛服务器进行交互。
拉取 token 的时机
CreateForm 初始化的时候拉取一次足够了,不太可能在这个页面停留 1 小时以上。
但是感觉还是封装成组件比较好,否则多个页面这些配置还要改 N 个地方。
TODO
- [X] go gin 后台生成上传凭证接口
- [X] 查看 ant design 官方组件的阿里云 OSS 直传示例代码,基于此梳理七牛云的逻辑
- [X] 封装成 react 组件
- [X] 编辑历史数据,报错:TypeError: items.map is not a function。fileList 参数,后台返回的是字符串,需要转换成 array
- [X] 上传完成后,可以预览
- [X] fileList 逻辑确认。删除等操作回调里
- 自定义 preview 界面。否则默认是新窗口打开视频播放,倒是可以接收。
七牛云上传地址
ant design upload 组件,action 属性需要填写对应的上传地址。 而七牛云不同地区 Bucket 有不同的上传地址,参考这里:
https://developer.qiniu.com/kodo/1671/region-endpoint-fq
例如,华南地区是:
https://upload-z2.qiniup.com
七牛接口返回
{"hash":"FuxTlDmDSHGp1ijpBEOo9LNZJnti","key":"FuxTlDmDSHGp1ijpBEOo9LNZJnti"}
key 即文件名,默认是七牛后台自动生成的。还是替换成自己的规则比较好。 需要在上传的时候,通过 key 指定文件名。
视频上传组件
import React from 'react';
import { Form, Upload, message, Button } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { uploadToken } from '@/services/ant-design-pro/api';
const QINIU_SERVER = 'https://upload-z2.qiniup.com'; // 华南地区
/**
* 视频上传组件
*
* props 值列表:
* - value: form 中的值。多个视频链接以英文逗号分隔
* - max: 最多可以上传几个视频。max = 1 可上传一张,不设置则可上传无限多。
**/
class QiniuUploadVideo extends React.Component {
constructor(props) {
super(props);
let _state = {
token: '',
filePrefix: '',
urlPrefix: '',
fileList: [],
max: this.props.max,
};
if (this.props.value) {
let urls = this.props.value.split(",");
let i = -1;
for (let url of urls) {
_state.fileList.push({
uid: i + "",
name: '视频',
status: 'done',
url: url,
})
}
}
this.state = _state;
}
async componentDidMount() {
await this.init();
}
init = async () => {
try {
const data = await uploadToken();
console.log(data);
this.setState({
token: data.uploadToken,
filePrefix: data.filePrefix,
urlPrefix: data.urlPrefix,
});
} catch (error) {
message.error(error);
}
};
handleChange = ({ file, fileList, event }) => {
const { status, response } = file
if (status === 'done') {
// 上传成功
const { key, hash } = response
if (key) {
message.success("上传成功")
let imgs = [];
for (let file2 of fileList) {
if (file2.url) {
imgs.push(file2.url);
} else {
imgs.push(this.state.urlPrefix + "/" + file2.response.key);
}
}
// 调用父组件 onChange 方法, 将新值传递回去
this.props.onChange(imgs.join(","))
} else {
message.error("上传失败")
}
}
this.setState({ fileList })
};
getExtraData = file => {
const { token, filePrefix } = this.state;
return {
token: token,
key: filePrefix + "_" + file.name,
};
};
render() {
const uploadButton = (
<Button icon={<UploadOutlined />}>点击上传视频</Button>
);
const props = {
action: QINIU_SERVER,
name: 'file',
fileList: this.state.fileList,
//listType: "picture-card",
onChange: this.handleChange,
data: this.getExtraData,
};
return (
<Upload {...props}>
{(this.state.max && this.state.fileList.length >= this.state.max) ? null : uploadButton}
</Upload>
);
}
}
export default QiniuUploadVideo;
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式