やりたいこと
multipart/form-dataでファイルを送信する際は、FormData
オブジェクトを作ってそれをそのまま送信する。
FormData
オブジェクトを作成するには<form>
タグを引数に取ってFormData
を初期化しても良いし、
空のFormData
オブジェクトを作ってそこにデータを足しても良いみたい。
(下記は空のFormData
の例)
// フォームにファイルを指定
let formData = new FormData();
formData.set("uploadFile", file, file.name);
// 送信
let xhr = new XMLHttpRequest();
xhr.open("PUT", "/your/api/url/");
xhr.send(formData);
ただ、こうすると送信時のfile
のContent-Type
がブラウザで判定されたMIMEタイプで送信されてしまう。
これを明示的に指定したい。
対策
ファイルをtype
指定付きでBlob
に変換することで、multipart/form-data送信時のContent-Typeも指定した値になる。
let blob = new Blob([file], {type: "application/zip"});
// フォームにblobを指定
let formData = new FormData();
formData.set("uploadFile", blob, file.name);
これはファイルの場合ですが、textや他のデータでもBlob
に変換すればContent-Typeを指定できるはず。
(記事末尾の参考記事も参考にしてみてください。)
サンプルコード
upload.html
<!DOCTYPE html>
<html>
<head>
<title>ファイルアップロードテスト</title>
</head>
<body>
<input type="file" onchange="fileChanged(this)"/>
<button id="button">send</button>
<script>
const button = document.getElementById("button");
let file;
// 送信ボタンクリック時
button.onclick = function() {
let blob = new Blob([file], {type: "application/zip"});
// フォームにblobを指定
let formData = new FormData();
formData.set("uploadFile", blob, file.name);
// 送信
let xhr = new XMLHttpRequest();
xhr.open("PUT", "/your/api/url/");
xhr.send(formData);
xhr.onerror = function(e) {
console.log("ERROR");
console.log(e);
}
xhr.onload = function(e) {
console.log("LOAD");
console.log(e);
console.log(xhr.status);
console.log(xhr.statusText);
console.log(xhr.responseText);
alert(xhr.responseText);
}
}
// ファイル選択時
function fileChanged(input) {
file = input.files[0];
console.log(file);
console.log(file.name);
}
</script>
</body>
</html>
参考記事