javascript ファイルのダウンロードとボタン連打防止

javascript でファイルをダウンロードするプログラムを作成した。
ダウンロードを開始するボタンは連打できないよう対処した。
(download.html)

<script>
function getFile(method, url, buttonid){

  var request = new XMLHttpRequest();

  request.onreadystatechange = function() {

    console.log(request.readyState);

    if(request.readyState === 1){

      document.getElementById(buttonid).disabled = true;

    }else if(request.readyState === 4 ){

      document.getElementById(buttonid).disabled = false;

      if(request.status === 200){
        
        var link = document.createElement("a");
        document.body.appendChild(link);
        link.href = window.URL.createObjectURL(request.response);
        link.download = url;
        link.click();
        document.body.removeChild(link);

      }

    }else{

    }

  };
  
  request.open(method, url, true);
  request.responseType = "blob"; //Blobオブジェクトとしてダウンロードする
  var body = null;
  if( method === 'POST' ){
    var formdata = document.getElementById("form_post");
    var params = [];
    for( var i = 0; i < formdata.length-1; i++ ){
      params.push(formdata[i].name + '=' + formdata[i].value);
    }
    body = params.join('&');
    console.log(body);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  }
  request.send(body);

}
</script>

<form id="form_get">
<input type="button" value="get" name="get" id="button_get" onclick="getFile('GET','http://localhost:4567/get','button_get')">
</form>

<form id="form_post">
<input type="text" name="a">
<input type="text" name="b">
<input type="button" value="post" name="post" id="button_post" onclick="getFile('POST','http://localhost:4567/post','button_post')">
</form>

指定したURLのファイルをダウンロードする関数getFile(method, url, buttonid)の引数は以下の通り。
method・・・get か post を指定する。
url・・・ファイルのurl。
buttonid・・・ダウンロード実行ボタンのid。ダウンロード中はこのボタンを無効にする。


ファイルをダウンロードさせるには?[JavaScript
https://atmarkit.itmedia.co.jp/ait/articles/1603/30/news026.html
【メモ】XMLHttpRequestのイベントについて
https://qiita.com/ShinyaKato/items/64b6726c361f5377b0f3



ファイルデータを送る処理は sinatra で書いた。
(sendfile.rb)

require 'sinatra'

before do
  response['Access-Control-Allow-Origin'] = '*'
end

get '/get' do
  sleep 5
  send_file 'wallpaper.jpg'
end

post '/post' do
  sleep 5
  logger.info "a:" + params[:a].to_s
  logger.info "b:" + params[:b].to_s
  send_file 'wallpaper.jpg'
end


http://xxx/download.html から http://xxx:4567/xxx を呼び出すとCORS のエラーが出たので、response['Access-Control-Allow-Origin'] = '*' を追加した。テストなので。。

Access to XMLHttpRequest at 'http://localhost:4567/get' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Sinatra】CORS の設定をする
https://takagi.blog/sinatra-cors/



webサーバを起動し、ルートディレクトリにdownload.htmlを置く。
webブラウザで、http://xxx/download.htmlにアクセスする。


sendfile.rb は、ruby で実行する。

$ ruby sendfile.rb
[2022-12-28 22:20:16] INFO  WEBrick 1.4.2
[2022-12-28 22:20:16] INFO  ruby 2.6.4 (2019-08-28) [x86_64-cygwin]
== Sinatra (v3.0.3) has taken the stage on 4567 for development with backup from WEBrick
[2022-12-28 22:20:16] INFO  WEBrick::HTTPServer#start: pid=1078 port=4567
...


get ボタンを押してみると、数秒間 get ボタンが無効になる。


post ボタンも、数秒間 post ボタンが無効になる。
テキストボックスに入力した値が、logger.info で表示できている。

$ ruby sendfile.rb
[2022-12-29 01:08:07] INFO  WEBrick 1.4.2
[2022-12-29 01:08:07] INFO  ruby 2.6.4 (2019-08-28) [x86_64-cygwin]
== Sinatra (v3.0.3) has taken the stage on 4567 for development with backup from WEBrick
[2022-12-29 01:08:07] INFO  WEBrick::HTTPServer#start: pid=1079 port=4567
I, [2022-12-29T01:08:21.755997 #1079]  INFO -- : a:1
I, [2022-12-29T01:08:21.756392 #1079]  INFO -- : b:2
::1 - - [29/Dec/2022:01:08:21 +0900] "POST /post HTTP/1.1" 200 150788 5.0359
::1 - - [29/Dec/2022:01:08:16 JST] "POST /post HTTP/1.1" 200 150788
http://localhost/ -> /post