モノクロタイム

I'm from the future!

【React】axiosを使用してmultipart/form-data形式の通信をする

こんにちは、れいじです。

年末なので趣味の開発に時間をつぎ込んでいます。Webサービスを作っているのですが、あまり複雑なシステムではないのでreduxなどは導入せずにシンプルに作っています。

APIとの通信に使用するモジュールとしてはredux-sagaとかredux-thunkとかまぁいろいろあるわけですが、上述の通りreduxは導入しないのでこれらは候補に入りません。

なので最近ナウいと噂のaxiosを使用してAPI通信を実装したいと思います。

github.com

やりたいこと

  • ReactAppでAPI通信をする。今回は画像を受け取り、APIに投げる処理を実装したい。

  • 画像をポストする場合の通信形式はmultipart/form-dataとする。

  • 通信メソッドはPOST。

ボタン側

※UIデザインにmaterial-uiを使用しています。そのあたりの記述はうまく読解してもらえればと

material-ui.com

<div>
    <input accept="image/*" multiple type="file" className="input" id="upload-img" onChange={this.uploadFile.bind(this)} />
    <label htmlFor="upload-img">
        <Button variant="contained" component="span" color="secondary" aria-label="Add" className="uploadIcon">
              <CameraIcon />
              UPLOAD
         </Button>
    </label>
</div>

ボタンを押すとファイル選択用ブラウザが開きます。画像を選択した後は、取得した画像をAPIにポストします。

画像を受け付ける部分(uploadFile())

 uploadFile(e) {
    this.setState({
      file: e.target.files[0],
    }, () => {
      this.sendFile();
    });
  };

最新の画像をStateに保持・更新した後にAPIに画像を送ります。

画像をAPIに送信する部分(sendFile())

いよいよaxiosが出てくる部分です

  sendFile() {
    // show loading modal
    this.setState({isLoading: true});
    const params = new FormData();
    params.append('file', this.state.file);
    axios
      .post(
        'https://api/upload',
        params,
        {
          headers: {
            'content-type': 'multipart/form-data',
          },
        }
      )
      .then((result) => {
        this.setState({
          isLoading: false
        });
      },
      )
      .catch(() => {
        console.log('upload failed...');
        this.setState({
          isLoading: false
        });
      });

axiosでPOST通信をするときのTipsとして、paramsをそのままjson形式で送信すると通信メソッドを.postで定義していてもOPTIONになってしまいます。

参考:

qiita.com

ここではパラメータをURLSearchParams()で定義してあげているのですが、今回私はmultipart/form-dataでデータを送りたいので、

const params = new FormData();
params.append('file', this.state.file);

と指定しています。

さらにヘッダーにも

{
    headers: {
        'content-type': 'multipart/form-data',
    },
}

をつけてあげます。これでOK。

f:id:yomoyamareiji:20181231112904p:plain

いいかんじにpostできました。