React antdesign upload组件自定义上传到S3

简介

关于上传到S3,本文服务模块使用的是‘aws-sdk’ putObject()上传。UI模块使用的是antd中的upload组件,在使用antd组件的时候发现官方提供的上传方式有两种:

  1. 使用路径上传,antd中有一个属性action需要上传到的地址。
  2. 使用自定义上传,antd中的customRequest。
    本文选用的是第二种,自定义上传会覆盖组件默认的上传行为,所以我们需要去定义progress、onSuccess、onError。
    本文会使用到的技术:React,Rxjs,采用TSLint校验。

先看简单的dom模块

不多说直接上代码,一个简单的自定义上传。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import React from 'react';
import { Subject } from 'rxjs';
import { Upload } from "antd";
import {IS3Config, Upload$ } from "../../../core/services/s3service";

interface IParam {
onProgress: ({ }, f: UploadFile) => void;
onSuccess: () => void;
onError: () => void;
file: UploadFile & { webkitRelativePath: string };
}
export default class UploadComponent extends React.Component {
public S3token: IS3Config = {}; // 您的S3临时令牌
public bucket: string = ''; // 您要上传到的bucket名字
public key: string = ''; // bucket下面的路径
private upload = (param: IParam) => {
Upload$(this.S3token, this.bucket, this.key, param).subscribe(
() => console.log('成功'),
() => console.log('失败'),
);
}
public render () {
return (
<Upload customRequest={this.upload}>
<Button>
<Icon type="upload" /> Upload
</Button>
</Upload>
);
}
}

‘aws-sdk’上传 服务模块

  1. 首先需要对上传进行配置,以下是一个对S3进行配置的函数。
    这个函数中需要您的S3临时令牌,令牌需要有对S3进行操作的权限。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // s3service.tsx
    // 引入模块
    import { Subject } from 'rxjs';
    import { config, S3, AWSError } from 'aws-sdk';
    import { PutObjectOutput} from '../../../node_modules/aws-sdk/clients/s3';
    import { UploadFile } from '../../../node_modules/antd/lib/upload/interface';
    // 配置S3的接口
    export interface IS3Config {
    AccessKeyId?: '';
    SecretAccessKey?: '';
    SessionToken?: '';
    }
    // 对S3进行配置
    export const createS3 = (cfg: IS3Config) => {
    const setting = { //您的S3临时令牌
    accessKeyId: cfg.AccessKeyId,
    secretAccessKey: cfg.SecretAccessKey,
    sessionToken: cfg.SessionToken,
    };
    config.update(setting);
    config.region = "us-east-1";

    const s3 = new S3({
    apiVersion: '2006-03-01',
    });
    return s3;
    };
  2. putObject 上传文件及自定义progress、success、error

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    interface IUpload {
    onProgress?: ({ }, f: UploadFile) => void; // 需要重写的antd的progress函数
    onSuccess?: () => void; // antd中progress百分百时的成功函数
    file: UploadFile; // 上传失败的progress函数
    onError: () => void;
    }
    export const Upload$ = (s3Config: IS3Config, bucket: string, key: string, body: IUpload): Subject<PutObjectOutput> => {
    const s3 = createS3(s3Config); //传入您的S3令牌
    const s3subject = new Subject(); //创建一个Subject主体
    s3.putObject( // s3上面的putObject方法 第一个参数是一个对象,第二个参数是一个函数,函数有两个值,1.表示上传失败,2.表示上传成功
    {
    Body: body.file, // 是文件类型
    Bucket: bucket, // 对应S3上的bucket
    Key: key, // 需要上传到的路径
    },
    (err: AWSError, resp: PutObjectOutput) => {
    if (err) {
    log(err);
    s3subject.error(err); // 上传失败时调用
    } else {
    s3subject.next(resp); // 上传成功时调用
    }
    }).on('httpUploadProgress', (progress) => { // 上传S3时‘httpUploadProgress’函数里可以定义progress
    const percent = 100 * progress.loaded / progress.total;
    // https://github.com/react-component/upload/blob/master/examples/customRequest.js onProgress 第一个参数是进度条的值,第二个参数是当前上传的文件
    // body.onProgress 是antd中的onProgress 重写的progress
    body.onProgress ? body.onProgress({ percent }, body.file) : void 0;
    if (percent === 100 && body.onSuccess) body.onSuccess(); // 上传到百分百时调用 antd中的onSuccess
    }).on('httpError', (err) => {
    if (err && body.onError) {
    log(err);
    body.onError();
    s3subject.error(err);
    }
    });
    return s3subject;
    };

感谢https://github.com/yalishizhude的指导

参考文献

https://github.com/react-component/upload/blob/master/examples/customRequest.js


https://ant.design/components/upload-cn/


https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property


作者信息:宁文飞,人和未来大数据前端工程师