戻る
2022/09/08

ファイル読み込み・Fetch API

ブラウザで稼働しJavaScript(js)プログラムからtextファイルを読み込み表示するプログラムの記録。

名簿などはエクセルで管理している場合も多く、エクセルでhtml形式にして保存することも出来るが、出来上がったhtmlは、なにやら複雑でよくわからないjavascriptが組み込まれていてあまり使う気にはならない。他にpdfにも変換出来るがこれも一長一短で、自分でカストマイズできるように作れないものかと思っていた。

前versionではXMLHttpRequestを使用したが、今回は同じくHTTPリクエストを発行するFetch APIを使ってAjax通信を行い、サーバーから取得したデータを表示する。
* Fetch : 人や物を取って[連れて]くること
* API : Application Programming Interfaceの略語で、「機能を公開しているソフトウェア」と「その機能を使いたいソフトウェア」をつなげる窓口のようなものを指す
* Ajax : AsynchronousとJavaScriptに、XMLを組み合わせて作られた造語 

Fetch API の概要 : Fetch API は、JavaScript を使ってサーバーに HTTP リクエストを送信できるインターフェースで、指定した URL からリソース(データ)を取得することができる。 XMLHttpRequest と同様の機能を持つが、よりシンプルで柔軟な API である。IE や一部のブラウザは対応していないが、主要なモダンブラウザで利用できる。
リソース(データ)を取得するためのリクエストの送信は、fetch() メソッドを使う
fetch() メソッドにリソースの URL を指定して呼び出すとリクエストが発行され、Response オブジェクトを結果に持つ Promise オブジェクトが返される。
Promise は非同期処理を扱うための仕組みで、Promise オブジェクトの then() メソッドに処理(コールバック関数)を記述することができる

参考 : XAMPPのダウンロード

webアプリケーションの疑似開発環境を作る。
 導入はこちらから XAMPP
 使い方 : XAMPPを導入したフォルダーのhtdocsフォルダーにtestフォルダーを作り html , css , javascriptプログラムを移行する。 XAMPPを起動し、メニューからApacheをstartしておき、ブラウザでhttp://localhost/test/readtxt.html と入力するとwebアプリケーションの疑似開発環境が使える。


サンプルデータ

dummy.csv


名前,名前(ひらがな),年齢 ,生年月日,性別 ,メールアドレス ,電話番号 ,郵便番号 ,住所
北風 聡美,きたかぜ さとみ,38,1984年2月18日,女,satomikitakaze@example.net,070-5981-7058,134-5048,東京都品川区南品川2-5-9
松沢 宏明,まつざわ ひろあき,76,1946年6月2日,男,matsuzawa_62@example.jp,050-8710-5333,062-6726,北海道札幌市北区北二十四条西4丁目2番5号
横瀬 誠,よこせ まこと,65,1956年11月27日,男,yokose_1127@example.org,090-8911-4466,187-0440,東京都港区虎ノ門3-5-6
丸山 毅,まるやま たかし,48,1974年6月13日,その他・不明,maruyama613@example.co.jp,050-2719-5034,802-3021,福岡県福岡市早良区干隈4丁目3番9号

................................500ライン.......................................



実際のサンプルコードを記述しておく

html


<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>text file read</title>
<style>
<!--
body {background:url("back_g1.gif");background-color:ivory;}
h1    {color:green;text-align:center;margin:0px;}
h5    {float:right;margin-right:50px;}
#txt {width:90%;margin:10px auto;font-size:14px;text-shadow:0px 0px 1px black;font-family:"Courier New", Consolas, monospace;} 
#txt span {color:blue;}
#modoru a:link , #modoru a:visited { 
      width:3%;
      display:block;
      text-decoration:none; 
      border:2px ridge ivory;
      color:ivory;
      text-shadow:1px 1px 0px black; 
      border-radius:5px;
      }
#return a:link , a:visited { 
    border:2px ridge gold;
    }
#modoru a:hover {
     color:red;
     background-color:lime;
     }
/*------------------ mobile responsive -----------------------------*/
@media screen and (max-width: 480px) { 
 h1 {
     width:80%;
     font-size:1.2rem;
     letter-spacing:0px;
    }
#modoru a:link , #modoru a:visited { 
      width:10%;
      display:block;
      text-decoration:none; 
      border:2px ridge ivory;
      color:ivory;
      text-shadow:1px 1px 0px black; 
      border-radius:5px;
      }
}
-->
</style>
<script src="js/readtxt.js"></script>
</head>
<body>
<div id="modoru"><a href="#" onClick="history.back(); return false;">戻る</a></div>
<h1><span id="title">ABC-XYZ会名簿</span></h1>
<h5>(テスト用架空データ)</h5>
<div style="clear:both;"></div>
<pre>
<div id="txt"></div>
</pre>
</div>
</body>
</html>


js/readtxt.js(全体)


// ------------------------------------------------ text file read on 非同期
// --------------------------------------------------------------------------
      var txt1 = txt2 = ""; 
      var t0 = t1 = t2 = t3 = t4 = t5 = t6 = t7 = t8 = "" ;
      var n = 1 ;  //  line number

      fetch("data/dummy.csv")
       .then(function(response){                        // response 
          if (!response.ok) {return Promise.reject(new Error("error"));}  //  error
          return response.text();                         // ok string utf-8
       }) 
       .then(function(text){
         display(text) ;
      }) 
      .catch(function(error){console.error("fetch error", error);  //  error処理
      });            // ここで セミコロン(;)

      // ---------------------- data handling 
       function display (text) {
           var txt_list = text.split('\n');                 // 改行で分ける
             for ( i = 0 ; i < txt_list.length-1 ; i++) {
                 var txt_list1 = txt_list[i].split(',') ;                       // split by separater
                 if ( i == 0 ) {                                                    // header line only 
                   for ( j = 0 ; j < txt_list1.length ; j++) {
                     if (j == 0 ) { t0 = txt_list1[j].padEnd(13,' ')}           // 名前
                    else if ( j == 1 ) { t1 = txt_list1[j].padEnd(10 ,' ')}       // ひらがな 
                    else if ( j == 2 ) { t2 = txt_list1[j].padEnd(5,' ')}        //  年齢 
                    else if ( j == 3 ) { t3 = txt_list1[j].padEnd(12 ,' ')}       // 生年月日 
                    else if ( j == 4 ) { t4 = txt_list1[j].padEnd(9 ,' ')}       // 性別 
                    else if ( j == 5 ) { t5 = txt_list1[j].padEnd(25 ,' ')}     // メールアドレス
                    else if ( j == 6 ) { t6 = txt_list1[j].padEnd(11 ,' ')}       // 電話番号
                    else if ( j == 7 ) { t7 = txt_list1[j].padEnd(7 ,' ')}         // 郵便番号
                    else if ( j == 8 ) { t8 = txt_list1[j].padEnd(10 ,' ')}     // 住所
                     txt1 = '<b>' +  'No.  ' + t0 + t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 +  '</b>'  ;
                  }   
                } 
               if ( i > 0 ) {  
                   for ( j = 0 ; j < txt_list1.length ; j++) {
                     if (j == 0 ) { t0 = txt_list1[j].padEnd(9,' ')}                // 名前
                     else if ( j == 1 ) { t1 = txt_list1[j].padEnd(10 ,' ')}          // ひらがな
                     else if ( j == 2 ) { t2 = txt_list1[j].padEnd(5 ,' ')}              //  年齢 
                     else if ( j == 3 ) { t3 = txt_list1[j].padEnd(12 ,' ') + ' '}   // 生年月日 
                     else if ( j == 4 ) { t4 = txt_list1[j].padEnd(8 ,' ')}    // 性別 
                     else if ( j == 5 ) { t5 = '<span>' + txt_list1[j].padEnd(30 ,' ') + '</span>'}       // メールアドレス
                     else if ( j == 6 ) { t6 = txt_list1[j].padEnd(14 ,' ')}       // 電話番号
                     else if ( j == 7 ) { t7 = txt_list1[j].padEnd(9 ,' ')}         // 郵便番号
                     else if ( j == 8 ) { t8 = txt_list1[j].padEnd(10 ,' ')}                // 住所
                     txt1 =  String(n).padStart(3,'0') + '. ' + t0 + t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 ;
        
                  }; // for  end j
                  n += 1 ;
                 }; // if i >0
        
                txt2 =  txt2 + txt1 + '<br>'
                document.getElementById("txt").innerHTML =  txt2 ;
     
             };   // for ( i = 0 ; i < txt_list.length-1 ; i++) {
       
          };  // function handle end
      
         // ----  end




js/readtxt.js (fetch)

fetch部分の解説


      fetch("data/dummy.csv")
       .then(function(response){                        // response 
          if (!response.ok) {return Promise.reject(new Error("error"));}  //  error
          return response.text();                         // ok string utf-8
       }) 
       .then(function(text){
         display(text) ;
      }) 
      .catch(function(error){console.error("fetch error", error);  // error処理
      });            // ここで セミコロン(;)


少々面倒だったのは、各項目を縦に揃えたかったこと。特に生年月日は半角数字と漢字が混在しており、数字の桁数の異なる場合がある。そのため後続の列が縦に揃わない。
 例)
  生年月日     性別
  1984年2月18日  男
  1956年11月27日  女

文字列の末尾に指定した文字列を繰り返し追加するpadEnd(12,' ')メソッドを使うが、htmlでは半角スペースを複数並べると一個しか使われない。
htmlタグの<pre> </pre>で挟むとこの制限はなくなるのに気がついた。但し等幅フォントをhtmlで指定する。

実行サンプル