利用Antd 的 Upload组件实现文件上传七牛云

4,798 阅读3分钟

首先我们的需求大概是这样的,我们需要使用AntdUpload组件将上传的文件传到七牛云上面,然后让七牛那边返回一个url即可。

在进行操作的之前可以先参考一下七牛那边的SDK文档:Node SDK.

完成需求的流程大概是下面这样:

  • 先获取到七牛那边的提供的一个token值
  • 然后将文件上传到七牛那边提供的一个url上面(一个post接口,要附带之前token提交上去)
  • 拿到返回的url地址即可

这里使用的框架是react,版本号是16.9.0。所以这里使用的是函数式组件来进行实现。

先安装一波依赖

npm install qiniu -S

然后新建一个qiniu.js的文件,用来得到七牛那边的token

import qiniu from 'qiniu';
import { Qiniu } from '../../secret';

qiniu.conf.ACCESS_KEY = Qiniu.AK;
qiniu.conf.SECRET_KEY = Qiniu.SK;
// 七牛那边的对应的bucket名称
const bucket = '';

export const getToken = () => {
    const putPolicy = new qiniu.rs.PutPolicy({
        scope: bucket
    })
    return putPolicy.uploadToken();
}

然后相对应的secret.js用来存储个人七牛的仓库的SKAK

其中secret.js的代码大致为这样(相关的SK和AK填写自己七牛云对应即可):

export const Qiniu = {
    AK:'',
    SK:''
}

这个文件上传的时候放在.gitignore里面就可以了。或者项目有CI支持的话,可以先用CI对文件进行一个加密也可以。

过程大概是这样,在使用upload进行组件的上传的时候,先使用beforeUpload获取到本次上传所需要的token值,然后把token填在上传的data里面,然后上传到七牛对应的QINIU_SERVER那边去,这样最后那边上传之后返回的url,上面这些过程都是利用Upload本身所提供的API来完成。具体实现过程可以参考下面的demo

import React, { useState, Fragment } from "react";
import { Form, Upload, Modal, Icon } from "antd";
import { getToken } from "utils/qiniu";

// 七牛默认的上传地址(即为post接口)
const QINIU_SERVER = "http://upload.qiniup.com";
// bucket绑定的URL
const BASE_QINIU_URL = "";
const FormItem = Form.Item;

function Demo(props) {
  const { getFieldDecorator } = props.form;
  // 用来预览弹出预览图片的Modal框框
  const [previewVisible, setPreviewVisible] = useState(false);
  const [previewImage, setPreviewImage] = useState("");
  // 存储七牛返回的token值
  const [token, setToken] = useState("");
  // 存取上传七牛返回的值
  const [fileList, setFileList] = useState([]);
  // antd form表单的一个排版设计
  const formItemLayout = {
    labelCol: {
      xs: { span: 24 },
      sm: { span: 8 }
    },
    wrapperCol: {
      xs: { span: 24 },
      sm: { span: 16 }
    }
  };
  // 预览
  const handlePreview = file => {
    setPreviewImage(file.url || file.thumbUrl);
    setPreviewVisible(true);
  };
  const handleChange = ({ file, fileList }) => {
    const { uid, name, type, thumbUrl, status, response = {} } = file;
    const fileItem = {
      uid,
      name,
      type,
      thumbUrl,
      status,
      url: BASE_QINIU_URL + (response.hash || "")
    };
    fileList.pop();
    fileList.push(fileItem);
    // 这里必须要用展开运算符,否则会有error,具体可以参考antd文档
    setFileList([...fileList]);
  };

  const getUploadToken = () => {
    const token = getToken();
    setToken(token);
  };

  const uploadButton = (
    <div>
      <Icon type="plus" />
      <div className="ant-upload-text">上传</div>
    </div>
  );
  return (
    <Fragment>
      <Form>
        <FormItem label="上传文件 " {...formItemLayout}>
          {getFieldDecorator("scwj", {
            rules: [
              {
                required: false
              }
            ]
          })(
            <>
              <Upload
                action={QINIU_SERVER}
                data={{ token }}
                listType="picture-card"
                beforeUpload={getUploadToken}
                fileList={fileList}
                onPreview={handlePreview}
                onChange={handleChange}
              >
                {fileList.length >= 1 ? null : uploadButton}
              </Upload>
            </>
          )}
        </FormItem>
      </Form>
      <Modal visible={previewVisible} footer={null} onCancel={handleCancel}>
        <img style={{ width: "100%" }} src={previewImage} alt="previewImg" />
      </Modal>
    </Fragment>
  );
}

export default Demo;