Archive for the ‘JavaScript’ Category

HTML5 – ファイル更新日時と新ZIP圧縮

水曜日, 9月 30th, 2015

・ファイルの日時
HTML5のファイル送信で、ファイルの更新日時を送り込むことができるようになりました。これまでもフォームから送られたファイルには、サイズと名前はありましたが、日時はありませんでした。HTML5でもその点は変わりませんが、送信時にJavaScriptでHTML5のfile-apiを使用して、ファイルの更新日時を取得できるようになりました。それを別のフォームID名で送り込めばいいわけです。これにより送られたファイルがサーバー上で日時を操作できるようになります。また同時にEXIFの撮影日時も取得するようにしました。これにより、画像に関しては撮影日時、更新日時、送信日時の順で有効なものをセットできるようになりました。

・HTML5でブラウザ処理が高度化
Ajaxによる画像の分割処理ができるようになりました。最近のデジカメ画像はものすごく大きいので、処理に大変時間がかかります。ともすると、Webではタイムアウトをおこします。そのためAjaxによる分割処理が必要なのですが、フォームの入力データが沢山あると、javascriptで一つづつ移すのは大変で、間違いのもととなります。
しかしIE11やChromeなどHTML5に完全対応したブラウザではfailesを含むformが一括扱えるようになりました。これにより、複雑で大量のフォームもAjaxで丸ごと送り出してやることができ、今回の分割処理を作ることができました。Googleのおかげで、MSも重い腰を上げ、ブラウザ処理が高度化しているといえます。FlashやオラクルJavaのような専用アプリの機能をどんどんカバーし始めています。

・ZIP圧縮の作り直し
ファイルの日時をサーバーで扱えるようになりましたが、それをそのままダウンロードすると日時は現在時刻になっていまします。FFFTPを使用すればそのまま書き込まれるようです。ブラウザで行うには、ZIP圧縮なら日時は変わらないだろうと考えていましたが、今までのプログラム(書庫を作りそこにファイルを追加する方法)では圧縮時刻になってしまうことが分かりました。ZIP圧縮は何もしなくても、ファイル情報がそのまま生きると思っていましたが、そうではなく、エントリーというものにファイル情報を設定しなおして、その中にデータを圧縮書き込みするようです。
今回、少し面倒ですがエントリーを作成して、その日時にファイル更新日時を設定してから、ファイルストリームを書き込む方法でプログラムを作り直しました。ついでにフォルダごと圧縮するfirstzipという方法(ファイル更新日時が生きる)も作り、「新ZIP圧縮」が揃いました。これでWEBサーバーに送り込まれたファイルの更新日時は各種処理の後、生かしたまま別のPCでダウンロードし、利用できます。

HTML5 – ファイルアップロード プログレスバー付

火曜日, 9月 30th, 2014

XPのサポート終了をきっかけに、ブラウザも一斉にIE11が主流になるという大変な変化が起こっています。IE11はWindows8のタッチパネル用のタッチイベントという独自の規格を装備していて、マウス操作がうまく動かないという現象が起きていました。その修正をしていたついでに、これが主流になるなら、HTML5とAjaxを使用した、複数ファイルアップロードを作ることにしました。jQueryを使用しない自前のAjaxでできてるので、jQueryのバージョンアップやIE対応を待つ必要がなく、自分で拡張したり、応用することができます。プログレスバーはその応用で作りました。ちなみに、jQueryで全て作っている人は、前述のIE11のタッチイベントの問題は、自力では解決できません。

複数ファイルの選択ができますか?お手持ちのブラウザで試してください。

対応のブラウザ
モダンブラウザのie11、chrome、safari5でOKです。safariは以前(4.0)から複数のファイルを選択できましたが、そのファイルをjavascriptで扱えない場合があります。最新バージョンのなら大丈夫です。
・Safari
windows版のsafariは5.1.7までありますが、全て動作しません。macのsafariは5.0から正常に動作することが分かりました。safari4.0は複数選択はできるが、JavaScriptでエラーを起こします。したがって、バージョンで判断して分岐させる予定です。

不便だったファイル送信
HTMLでのファイル送信は、大変不便なものでした。選べるのは1ファイルだけ、しかも選んだファイルの操作は一切できず、だだブラウザまかせでボタンを押すだけという、とてもアプリとはいえない粗末なインターフェースでした。そのため多くのWeb開発者は、Flashで開発されたアップローダーを使用したり、独自にアップローダー開発したりしてファイル送信のインターフェースを開発していました。GoogleやWordPressもFlashアップローダーを使用していました。
このファイル操作の不便さは、HTMLやjavascriptでPC内をアクセスできないようにするという意味があるようです。簡単に公開するとjavascriptでPCの個人情報を皆持っていかれてしまうという危険があるわけです。インターネット(HTML)は便利さと危険性のせめぎ合いなわけです。
その理由からか、初期のiPadは1ファイルのファイル送信もグレーアウトで使用できなくしてありました。Flashのアップローダーはもちろん使えません。これでは画像とかのアップロードはどうするんだという感じでした。

ようやく使えるmultiple属性

<input type="file" name="fff" multiple size="20">

↑上記の複数ファイル選択のタグです。
HTML5で追加されたmultiple属性は、ChromeやSafariでは以前から対応していましたが、IE(IE9)では使えませんでした。IE11でやっと使えるようになりました。IE11は前述のタッチイベントの問題がありますが、XPがなくなれば、これを使うしかしかありません。HTML開発者には悪評高いIEも、ようやくHTML5に対応できたといえます。このタグをフォームに貼って送信すれば、複数のファイルがサーバーに送られます。

Ajaxファイルアプリケーション
このファイル情報をAjax(Javascript)で扱うことにより、より複雑で、ユーザーインターフェースのよいファイルアプリケーションを作ることができます。そのためにHTML5ではJavascriptでファイルとフォームを扱えるようにするオブジェクトが追加されています。それが以下のFileApiとFormDataです。
ここでは、このブラウザがFileApiとFormDataが使えるかどうかをチェックしています。その情報をサーバーに送ります。次にフォームで入力された複数のファイルデータを、別に用意した作業用のフォームに一個づつコピーします。作業用のフォームにコピーしたファイルをAjaxでサーバーに送るという仕組みで、それを選択されたファイル数だけ繰り返します。送信する前にこれも新しく追加されたupload.progressイベントを設定しています。
これまでのHTML、Javascriptでは実現できなかったアプリケーションがこれで可能になります。Googleを始めとするクラウド化の企業やjQueryプログラマー達の意思の結果だと思います。

//Fileと.FormDataが使用できるか調べる
window.onload = function(){
  if (window.File && window.FormData){
    document.fm01.fapi.value = 1 ;
  }
}

//別フォームへ指定の1ファイルをコピー
var fm = document.fmwk;
var fdata = new FormData(fm);
var fw = document.form1.fs.files[ban-1];
fdata.append("afile",fw);

//Ajaxでフォームを送信 (※概要です)
var req = new XMLHttpRequest();
//プログレス用のイベントハンドラを設定
req.upload.addEventListener('progress',progress_s,false);
//コールバック関数を設定
req.onreadystatechange = function(){ 
    resp_s(mode,ban,req);
}
//aurl=受信URL
req.open("POST",aurl,true);
req.send(fdata);

プログレスバーを作成
プログレスハンドラには、アップロードの総量と処理量が送られてきます。それをパーセントに計算して、ボックスの幅に設定してやります。これでプログレスバーが動きます。

 

//プログレス ハンドラ
function progress_s(evt) {
  if (evt.lengthComputable) {
    var lsu = evt.loaded;
    var tsu = evt.total;
    var per = Math.round(lsu * 100 / tsu);
    document.getElementById('progress').style.width = 
      per + "%";
  }
}

プログレスバーボックスモデル
<div style="width:270px;height:10px;
  background:#dcdcdc;">
<div id="progress" style="width:150px;height:10px;
  background-color:#8FC31F;font-size:2px">
</div>
</div>

プログレスバー全ファイル
実際には、プログレスハンドラには、ブラウザへの読み込み量が送られてくるようで、送信済みとはタイムラグが発生し、スムーズに動きません。そのため、ここでは全体のファイル数、処理済みのファイル数を同時に計算して、プログレスハンドラでは0.75の処理としています。残りは、コールバック関数内で、1ファイル分を100%処理済み(終了)としてやります。これで、全体のプログレスバーがスムーズに動きます。

//プログレス ハンドラ
//f_ban filesu はグローバル
function progress_s(evt) {
 if (evt.lengthComputable) {
  var bun = evt.loaded / evt.total;
  var fsumi = (f_ban - 1) / filesu;
  var fbun = 1 / filesu * 0.75 ;
  var fper = Math.round((fsumi + (fbun * bun)) * 100);
  document.getElementById('progressf').style.width = 
   fper + "%";
 }
}
//コールバック関数(1ファイル終了)
function refs_s(ban,rtxt){
 ……
 ……
  var per = Math.round(ban * 100 / filesu);
 document.getElementById('progressf').style.width = 
  per + "%";
}

ドラッグ&ドロップは延期
サーバー側のアプリは、従来の1ファイル受信用のものが流用できますから、phpでもaspでも自由に開発できると思います。
HTML5では、ファイルのドラッグ&ドロップのインターフェースも追加されています。モダンなスタイルでいいという人もいますが、ファイル送信には間違い易いという人もいます。クラウドは若い人達だけが使うものではありません。やはり間違いなく使えるというのが一番大事なことだと思います。したがって今回はドラッグ&ドロップの開発は延期することにしました。いずれまた……。