React antdesign upload元件自定義上傳到S3

genetalks_大資料發表於2019-04-04

簡介

關於上傳到S3,本文服務模組使用的是‘aws-sdk’ putObject()上傳。UI模組使用的是antd中的upload元件,在使用antd元件的時候發現官方提供的上傳方式有兩種:

  1. 使用路徑上傳,antd中有一個屬性action需要上傳到的地址。
  2. 使用自定義上傳,antd中的customRequest。 本文選用的是第二種,自定義上傳會覆蓋元件預設的上傳行為,所以我們需要去定義progress、onSuccess、onError。 本文會使用到的技術:React,Rxjs,採用TSLint校驗。

先看簡單的dom模組

不多說直接上程式碼,一個簡單的自定義上傳。

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進行操作的許可權。
// 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;
};

複製程式碼
  1. putObject 上傳檔案及自定義progress、success、error
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


作者資訊:寧文飛,人和未來大資料前端工程師

相關文章