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

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

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)