JavaScript
Django
blob
fetch

Webアプリでファイルのアップロードからダウンロードまでを一度の非同期通信で行う

「クライアントからファイルを受け取り、サーバからもファイルを返す」という処理を1回のユーザ操作で実現したく調べた結果、fetch api、blobを使って実装したのでサンプルを記載しておきます。

サーバ側はDjangoです。


HTML側


sample.html

<!DOCTYPE html>

<html lang="ja">
<head>
<title>fetch sample</title>
</head>
<body>
<form name="upload_form" onsubmit="myFetch()" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input id="upload_file" type="file" name="file">
<input type="submit" value="送信">
</form>

<script type="text/javascript">
function myFetch(event) {
// HTMLでの送信をキャンセル これをしないとページがリフレッシュされる
event.preventDefault();

let fd = new FormData( document.getElementById('upload_form') );

fetch("/hogeURL", {
// ファイルを送信
method: "POST",
body: fd
}).then(response => response.blob())
.then(myBlob => {
// サーバからのレスポンスが完了
// サーバ処理でエラーが起きてもここに来る
console.log('完了');

// 内部的にBlobオブジェクトに対するリンクを生成&クリックしてダウンロード
let a = document.createElement("a");
a.style = "display: none";
a.href = URL.createObjectURL(myBlob);
a.download = 'ダウンロード用ファイル名';
document.body.appendChild(a);
a.click();
}).catch(function(error) {
console.log('エラー:', error.message);

});
}
</script>

</body>
</html>



サーバ側


views.py

def upload(request):

# サーバ内での処理の例 アップロードされたファイルを保存
req_file = request.FILES['file']
destination = open('ファイルを保存するパス', 'wb')
for chunk in req_file.chunks():
destination.write(chunk)

# ファイルを返却
response = HttpResponse(open('返却するファイルのパス', 'rb').read(), content_type='ファイルのMIME type')
response['Content-Disposition'] = 'attachment; filename="返却時のファイルの名称"'

return response



参考

Fetch API