HTML5 File APIを使用したFlexでのファイルのドラッグアンドドロップ

こんにちは 最近、Flexの1つのWebアプリケーションでは、ドラッグアンドドロップで写真をアップロードする必要がありました。 Flashでは、これを直接実装することはできませんが、AIRアプリケーションにはこの機能があります。 この問題を解決するには、HTML5 File APIを使用する必要がありました。



したがって、問題の解決策はいくつかの段階に分けられます。 最初のステップは、File APIを使用したドラッグアンドドロップファイルの処理です。 ダウンロードされたすべてのファイルはリストに追加され、そこからフラッシュに転送されます。



 $(document).ready(function() { var dropZone = $('div#dropZone'); //    if (typeof(window.FileReader) == 'undefined') { dropZone.text('  !'); dropZone.addClass('error'); } //   Drop dropZone[0].ondrop = function(event) { event.preventDefault(); dropZone.removeClass('hover'); dropZone.addClass('drop'); displayFiles(event.dataTransfer.files); }; }); //-------------------------------------------------------------------------------------------------- var fileList = new Array(); function displayFiles(files) { $.each(files, function(i, file) { var imgList = $('ul#img-list'); var maxFileSize = 20*1000000; //    - 1 . if (!file.type.match(/image.*/)) { //    return true; } //   li     ,  //      file,    File (  ) var li = $('<li/>').appendTo(imgList); $('<div/>').text(file.name).appendTo(li); //    if (file.size > maxFileSize) { $('<div/>').text('  !').appendTo(li); } else { var img = $('<img/>').appendTo(li); li.file = file; //   FileReader     ,     //     var reader = new FileReader(); reader.onload = (function(aImg, file) { return function(e) { aImg.attr('src', e.target.result); aImg.attr('width', 75); file.f_data = e.target.result; //       fileList.push(file); }; })(img, file); reader.readAsDataURL(file); } }); } //--------------------------------------------------------------------------------------------------
      
      





HTML flex , div, .

<div style="float:left"> </div> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" id="web-client" width="800px" align="middle" height="600px"> <param name="allowScriptAccess" value="sameDomain"> <param name="allowFullScreen" value="false"> <param name="movie" value="dd_test.swf"><param name="quality" value="high"><param name="bgcolor" value="#cccccc"><embed src="test.swf" quality="high" bgcolor="#cccccc" name="web-client" allowscriptaccess="sameDomain" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="https://www.adobe.com/go/getflashplayer" width="800" align="middle" height="600"> </object> <div id="dropzone" style="float:left"> <p> , .</p> <ul id="img-list"></ul> </div>









$(document).ready(function() { var dropZone = $('div#dropZone'); // if (typeof(window.FileReader) == 'undefined') { dropZone.text(' !'); dropZone.addClass('error'); } // Drop dropZone[0].ondrop = function(event) { event.preventDefault(); dropZone.removeClass('hover'); dropZone.addClass('drop'); displayFiles(event.dataTransfer.files); }; }); //-------------------------------------------------------------------------------------------------- var fileList = new Array(); function displayFiles(files) { $.each(files, function(i, file) { var imgList = $('ul#img-list'); var maxFileSize = 20*1000000; // - 1 . if (!file.type.match(/image.*/)) { // return true; } // li , // file, File ( ) var li = $('<li/>').appendTo(imgList); $('<div/>').text(file.name).appendTo(li); // if (file.size > maxFileSize) { $('<div/>').text(' !').appendTo(li); } else { var img = $('<img/>').appendTo(li); li.file = file; // FileReader , // var reader = new FileReader(); reader.onload = (function(aImg, file) { return function(e) { aImg.attr('src', e.target.result); aImg.attr('width', 75); file.f_data = e.target.result; // fileList.push(file); }; })(img, file); reader.readAsDataURL(file); } }); } //--------------------------------------------------------------------------------------------------





HTML flex , div, .

<div style="float:left"> </div> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" id="web-client" width="800px" align="middle" height="600px"> <param name="allowScriptAccess" value="sameDomain"> <param name="allowFullScreen" value="false"> <param name="movie" value="dd_test.swf"><param name="quality" value="high"><param name="bgcolor" value="#cccccc"><embed src="test.swf" quality="high" bgcolor="#cccccc" name="web-client" allowscriptaccess="sameDomain" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="https://www.adobe.com/go/getflashplayer" width="800" align="middle" height="600"> </object> <div id="dropzone" style="float:left"> <p> , .</p> <ul id="img-list"></ul> </div>









 $(document).ready(function() { var dropZone = $('div#dropZone'); //    if (typeof(window.FileReader) == 'undefined') { dropZone.text('  !'); dropZone.addClass('error'); } //   Drop dropZone[0].ondrop = function(event) { event.preventDefault(); dropZone.removeClass('hover'); dropZone.addClass('drop'); displayFiles(event.dataTransfer.files); }; }); //-------------------------------------------------------------------------------------------------- var fileList = new Array(); function displayFiles(files) { $.each(files, function(i, file) { var imgList = $('ul#img-list'); var maxFileSize = 20*1000000; //    - 1 . if (!file.type.match(/image.*/)) { //    return true; } //   li     ,  //      file,    File (  ) var li = $('<li/>').appendTo(imgList); $('<div/>').text(file.name).appendTo(li); //    if (file.size > maxFileSize) { $('<div/>').text('  !').appendTo(li); } else { var img = $('<img/>').appendTo(li); li.file = file; //   FileReader     ,     //     var reader = new FileReader(); reader.onload = (function(aImg, file) { return function(e) { aImg.attr('src', e.target.result); aImg.attr('width', 75); file.f_data = e.target.result; //       fileList.push(file); }; })(img, file); reader.readAsDataURL(file); } }); } //--------------------------------------------------------------------------------------------------
      
      





HTML flex , div, .

<div style="float:left"> </div> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" id="web-client" width="800px" align="middle" height="600px"> <param name="allowScriptAccess" value="sameDomain"> <param name="allowFullScreen" value="false"> <param name="movie" value="dd_test.swf"><param name="quality" value="high"><param name="bgcolor" value="#cccccc"><embed src="test.swf" quality="high" bgcolor="#cccccc" name="web-client" allowscriptaccess="sameDomain" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="https://www.adobe.com/go/getflashplayer" width="800" align="middle" height="600"> </object> <div id="dropzone" style="float:left"> <p> , .</p> <ul id="img-list"></ul> </div>









$(document).ready(function() { var dropZone = $('div#dropZone'); // if (typeof(window.FileReader) == 'undefined') { dropZone.text(' !'); dropZone.addClass('error'); } // Drop dropZone[0].ondrop = function(event) { event.preventDefault(); dropZone.removeClass('hover'); dropZone.addClass('drop'); displayFiles(event.dataTransfer.files); }; }); //-------------------------------------------------------------------------------------------------- var fileList = new Array(); function displayFiles(files) { $.each(files, function(i, file) { var imgList = $('ul#img-list'); var maxFileSize = 20*1000000; // - 1 . if (!file.type.match(/image.*/)) { // return true; } // li , // file, File ( ) var li = $('<li/>').appendTo(imgList); $('<div/>').text(file.name).appendTo(li); // if (file.size > maxFileSize) { $('<div/>').text(' !').appendTo(li); } else { var img = $('<img/>').appendTo(li); li.file = file; // FileReader , // var reader = new FileReader(); reader.onload = (function(aImg, file) { return function(e) { aImg.attr('src', e.target.result); aImg.attr('width', 75); file.f_data = e.target.result; // fileList.push(file); }; })(img, file); reader.readAsDataURL(file); } }); } //--------------------------------------------------------------------------------------------------





HTML flex , div, .

<div style="float:left"> </div> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" id="web-client" width="800px" align="middle" height="600px"> <param name="allowScriptAccess" value="sameDomain"> <param name="allowFullScreen" value="false"> <param name="movie" value="dd_test.swf"><param name="quality" value="high"><param name="bgcolor" value="#cccccc"><embed src="test.swf" quality="high" bgcolor="#cccccc" name="web-client" allowscriptaccess="sameDomain" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="https://www.adobe.com/go/getflashplayer" width="800" align="middle" height="600"> </object> <div id="dropzone" style="float:left"> <p> , .</p> <ul id="img-list"></ul> </div>











2番目のステップは、ダウンロードしたファイルをフラッシュに転送することです。 外部の世界と通信するために、FlashにはExternalInterfaceクラスがあり、JS関数を呼び出したり、Flash関数を呼び出したりできるようにします。 残念ながら、Flashからの関数の呼び出しは安定して機能しなかったため、内部でタイマーを開始し、JS関数を呼び出してダウンロード済みのファイルを転送する必要がありました。

主な問題は、写真送信の形式でした。 Flashの内部では、 ByteArrayクラスのオブジェクトとして写真を扱うのが便利でした。 JSにはByteArrayクラスの類似物がないため、送信中にbase64で追加のデータ変換を使用する必要がありました。 File APIには、対応する関数readAsDataURL()があり、base64エンコードされた文字列としてファイルを返します。 結果の文字列をフラッシュに渡し、 Base64Decoderを使用して、元の写真を含むByteArrayクラスのオブジェクトを取得します。

 // Flex ,     var dragTimer:Timer; var file_count_already_have:int; //   -  JS  ,   JS -   public function init_draginteface():void { dragTimer = new Timer(3*1000,0); //  3  dragTimer.addEventListener(TimerEvent.TIMER, dragTimerEvent); dragTimer.start(); file_count_already_have = 0; } //--------------------------------------------------------------------------- public function dragTimerEvent(e:TimerEvent):void { dragTimer.stop(); if(ExternalInterface.available) { var file_count:int = ExternalInterface.call("dropFileCount"); // JS -,      if (file_count>0) { for(var i:int = file_count_already_have ; i<file_count; i++) { dragImageFromJS(i); } file_count_already_have = file_count; } dragTimer.start(); } } //--------------------------------------------------------------------------- public function dragImageFromJS(i:int):void { var file_size:int = ExternalInterface.call("getFileSize", i); //    var file_name:String = ExternalInterface.call("getFileName", i); //   var file_ba:ByteArray = new ByteArray; var base64dec:Base64Decoder = new Base64Decoder(); var start_load:uint = getTimer(); base64dec.decode(ExternalInterface.call("getFile", i)); //       base64 var load_time:uint = getTimer() - start_load; file_ba = base64dec.toByteArray(); if(file_ba != null) { trace(""); trace("add new item [file_name: "+file_name+"] [file_size:"+file_size.toString()+"] [fr_ba_size: "+file_ba.length + "] [load_time: "+load_time.toString()+"]"); loadFromByteArray(file_ba); //   Flex  } }
      
      









// Flex , var dragTimer:Timer; var file_count_already_have:int; // - JS , JS - public function init_draginteface():void { dragTimer = new Timer(3*1000,0); // 3 dragTimer.addEventListener(TimerEvent.TIMER, dragTimerEvent); dragTimer.start(); file_count_already_have = 0; } //--------------------------------------------------------------------------- public function dragTimerEvent(e:TimerEvent):void { dragTimer.stop(); if(ExternalInterface.available) { var file_count:int = ExternalInterface.call("dropFileCount"); // JS -, if (file_count>0) { for(var i:int = file_count_already_have ; i<file_count; i++) { dragImageFromJS(i); } file_count_already_have = file_count; } dragTimer.start(); } } //--------------------------------------------------------------------------- public function dragImageFromJS(i:int):void { var file_size:int = ExternalInterface.call("getFileSize", i); // var file_name:String = ExternalInterface.call("getFileName", i); // var file_ba:ByteArray = new ByteArray; var base64dec:Base64Decoder = new Base64Decoder(); var start_load:uint = getTimer(); base64dec.decode(ExternalInterface.call("getFile", i)); // base64 var load_time:uint = getTimer() - start_load; file_ba = base64dec.toByteArray(); if(file_ba != null) { trace(""); trace("add new item [file_name: "+file_name+"] [file_size:"+file_size.toString()+"] [fr_ba_size: "+file_ba.length + "] [load_time: "+load_time.toString()+"]"); loadFromByteArray(file_ba); // Flex } }











 //JS -,    Flex  function dropFileCount() //   { return fileList.length; } //-------------------------------------------------------------------------------------------------- function getFile(i) //     { var data = fileList[i].f_data; var data_cat = data.substr(23); return data_cat; } //    ,   ,    //data:image/jpeg;base64,/9j/4U3ARXhpZgAASUkq //-------------------------------------------------------------------------------------------------- function getFileSize(i) { return fileList[i].size; } //-------------------------------------------------------------------------------------------------- function getFileName(i) { return fileList[i].name; } //--------------------------------------------------------------------------------------------------
      
      









//JS -, Flex function dropFileCount() // { return fileList.length; } //-------------------------------------------------------------------------------------------------- function getFile(i) // { var data = fileList[i].f_data; var data_cat = data.substr(23); return data_cat; } // , , //data:image/jpeg;base64,/9j/4U3ARXhpZgAASUkq //-------------------------------------------------------------------------------------------------- function getFileSize(i) { return fileList[i].size; } //-------------------------------------------------------------------------------------------------- function getFileName(i) { return fileList[i].name; } //--------------------------------------------------------------------------------------------------











その結果、ドラッグアンドドロップで写真をFlexアプリケーションにアップロードできます。 ByteArrayから写真を表示するための小さなコード。

 <mx:Script> <![CDATA[ // Flex       ByteArray public function loadFromByteArray(data:ByteArray):void { _loader = new Loader(); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,_load_loader_complete); _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorOnLoad); _loader.loadBytes(data); } public function _load_loader_complete(e:Event):void { _loader.removeEventListener(Event.COMPLETE,_load_loader_complete); var bitmapIm:Bitmap = Bitmap(e.target.content); this.itemIm.addChild(bitmapIm); } ]]> </mx:Script> <mx:Image source="" id="itemIm" maxWidth="100" maxHeight="100" horizontalAlign="left" verticalAlign="top"/>
      
      









<mx:Script> <![CDATA[ // Flex ByteArray public function loadFromByteArray(data:ByteArray):void { _loader = new Loader(); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,_load_loader_complete); _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorOnLoad); _loader.loadBytes(data); } public function _load_loader_complete(e:Event):void { _loader.removeEventListener(Event.COMPLETE,_load_loader_complete); var bitmapIm:Bitmap = Bitmap(e.target.content); this.itemIm.addChild(bitmapIm); } ]]> </mx:Script> <mx:Image source="" id="itemIm" maxWidth="100" maxHeight="100" horizontalAlign="left" verticalAlign="top"/>











このソリューションには大きなマイナス点が1つあります。大きな写真をダウンロードするとき、ブラウザーはプロセッサーを大幅にロードします。 おそらくより良い方法がありますが、私はそれを見つけませんでした。



ps実例へのリンク。広告とは考えないでください。プロジェクトはローカルで、異なる視聴者向けに設計されています。



All Articles