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