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-Type
に multipart/form-data
が自動で指定されます。ここまでなら、署名付きURL生成時にContnent-Type
に multipart/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を使おうとしてはならない」