share facebook facebook twitter menu hatena pocket slack

2018.12.25 TUE

Google Cloud Storageの署名付きURLに対してaxiosでPUTするときにFormDataを使おうとしてはならない

甲斐 甲

WRITTEN BY 甲斐 甲

Google Cloud Platform その2 Advent Calendar 2018の6日目の投稿です。

axiosでファイルアップロードしようとして調べると、FormDataを利用する手順が世の中には数多くあります。

axios/axios: Promise based HTTP client for the browser and node.js
https://github.com/axios/axios

ただ、Google Cloud Storage(GCS)の署名付きURLに対してPUTする場合、FormDataは利用できないので、お気をつけください。

利用できない理由

FormDataは複数項目をまとめてアップロードできる仕組みで、Contnent-Typemultipart/form-data が自動で指定されます。ここまでなら、署名付きURL生成時にContnent-Typemultipart/form-data を指定すれば良いだけなのですが、multipart/form-data の場合、複数項目をアップロードする前提なので、区切り文字Boundary が含まれます。

こいつがリクエスト時にランダムで生成されるため、署名付きURLでContnent-Type に指定するにも指定できず詰みます。(詰みました~

だめな感じの実装(イメージ)

検証につかれて実行可能なコードを用意するのが疲れました

let uploadUrl = '';
await axios.get(`${apiRootUrl}signed_url?filename=${filename}&content_type=${contentType}`)
.then((res) => {
  uploadUrl = res.data.signed_url;
})
.catch((error) => {
  throw error;
});

const options = {
  headers: {
    'Content-Type': file.type, // ここで指定しても適用されないTT
  },
};

let data = new FormData();
data.append('file', file);
await axios.put(uploadUrl, data, options)
.then((res) => {
  console.log('成功!');
})
.catch((error) => {
  throw error;
});

いい感じの実装(イメージ)

散々ハマった挙げ句、動いた実装から一部持ってきました

let uploadUrl = '';
await axios.get(`${apiRootUrl}signed_url?filename=${filename}&content_type=${contentType}`)
.then((res) => {
  uploadUrl = res.data.signed_url;
})
.catch((error) => {
  throw error;
});

const options = {
  headers: {
    'Content-Type': file.type,
  },
};

await axios.put(uploadUrl, file, options)
.then((res) => {
  console.log('成功!');
})
.catch((error) => {
  throw error;
});

参考

axios/axios: Promise based HTTP client for the browser and node.js
https://github.com/axios/axios

multipart/form-dataのリクエストで地味にハマったメモ – Qiita
https://qiita.com/Zaki_Tk/items/073f597d52f6fd8e3dcd

FormData オブジェクトの利用 – ウェブデベロッパーガイド | MDN
https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects

元記事はこちら

Google Cloud Storageの署名付きURLに対してaxiosでPUTするときにFormDataを使おうとしてはならない

甲斐 甲

甲斐 甲

2018/7にJOIN。 最近の好みはサーバレスです。なんでもとりあえず試します。

cloudpack

cloudpackは、Amazon EC2やAmazon S3をはじめとするAWSの各種プロダクトを利用する際の、導入・設計から運用保守を含んだフルマネージドのサービスを提供し、バックアップや24時間365日の監視/障害対応、技術的な問い合わせに対するサポートなどを行っております。
AWS上のインフラ構築およびAWSを活用したシステム開発など、案件のご相談はcloudpack.jpよりご連絡ください。