ant design 组件上传视频直传七牛云

文章目录

    由于视频文件太大,不适合通过自己服务器中转一层,还是在前端直接传到七牛云合理。

    文档

    • 七牛云 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 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式