<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>File API &#8211; Mach3.laBlog</title>
	<atom:link href="https://blog.mach3.jp/tag/file-api/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.mach3.jp</link>
	<description></description>
	<lastBuildDate>Tue, 03 Dec 2013 01:12:17 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>
	<item>
		<title>&#034;Drag and Drop&#034; &#8211; Alphabetical Advent Calendar 2013</title>
		<link>https://blog.mach3.jp/2013/12/03/jaac2013-d-drag-and-drop.html</link>
		
		<dc:creator><![CDATA[mach3]]></dc:creator>
		<pubDate>Tue, 03 Dec 2013 01:12:17 +0000</pubDate>
				<category><![CDATA[Laboratory]]></category>
		<category><![CDATA[Advent Calendar 2013]]></category>
		<category><![CDATA[Drag and Drop]]></category>
		<category><![CDATA[File API]]></category>
		<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">http://blog.mach3.jp/?p=3640</guid>

					<description><![CDATA[&#8220;D&#8221; は Drag and Drop の &#8220;D&#8221;。 ローカルファイルをブラウザにドロップする ファイルをブラウザにドロップすることでアップロードしたりコンテンツを表示した [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>&#8220;D&#8221; は Drag and Drop の &#8220;D&#8221;。</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh5.googleusercontent.com/-8u61c5QavOA/UqR4gFYw44I/AAAAAAAACYg/AWzEKd6Dn8E/s400/ac2013-d.png" alt="D"/></figure>



<p></p>



<span id="more-3640"></span>



<h2 class="wp-block-heading">ローカルファイルをブラウザにドロップする</h2>



<p>ファイルをブラウザにドロップすることでアップロードしたりコンテンツを表示したりするインターフェイスは、 最近では色々なサービスに取り入れられています。 身近な物でいえば Gmail のWebメールのファイル添付や、各種写真共有サービスのアップロード、 WordPress のメディアアップロード等でも使われています。 <a href="http://codemirror.net/">CodeMirror</a> ではテキストファイルをエディタにドロップすると内容を展開してくれます。</p>



<p>ローカルファイルのドロップは <strong>drop</strong> イベントや <strong>File API</strong> 等を使用して実現されています。 <strong>File API</strong> は現状では実装していない環境があったり、実装していてもメソッドが足りなかったりする模様ですが、 将来的にはきっとスタンダードな機能になるでしょう。 （尚、IEは10以降で File API をサポートしています）</p>



<h2 class="wp-block-heading">アプリケーションの習作</h2>



<p>今回はファイルをページにドロップするとその内容を表示するだけのアプリケーションを習作してみます。 File API をサポートする環境のみを想定します。</p>



<p>※サンプルコードの単純化の為、jQueryを使用します。</p>



<h3 class="wp-block-heading">イベントの設定</h3>



<p>まずファイルのドロップの検知をする為の準備をするのですが、デフォルトの処理を無効化しておかなければなりません。 これを書いておかないと、ファイルそのものにページごと遷移してしまいますね。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">$(<span class="hljs-built_in">window</span>).on(<span class="hljs-string">"drop dragover"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    e.preventDefault();
});
</code></span></pre>


<p>次に、ドロップを受ける要素のイベントを設定します。 今回はドキュメント全体に設定し、ページのどこにドロップしても働くようにしちゃいます。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-comment">// dropHandler関数の中でファイルを受け取る処理をします</span>
$(<span class="hljs-built_in">document</span>).on(<span class="hljs-string">"drop"</span>, dropHandler);
</code></span></pre>


<h3 class="wp-block-heading">イベントハンドラの中で処理をする</h3>



<p>dropHandler関数の中では、こんな事をしようと思います。</p>



<ol class="wp-block-list">
<li>ドロップされたファイル群を取得する</li>



<li>ファイルのタイプを調べる</li>



<li>テキストと画像で処理を分けてページにappendする</li>
</ol>



<p>ドロップされたファイル群を取得するには、引数のEventオブジェクトにぶらさがっている <strong>dataTransfer</strong> オブジェクトの中身を参照します。 jQueryのon()で設定した場合は、<strong>originalEvent</strong> の中に埋もれていますので注意しましょう。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">var</span> dropHandler = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    <span class="hljs-comment">// 通常は e.dataTransfer.files</span>
    <span class="hljs-keyword">var</span> files = e.originalEvent.dataTransfer.files;
};
</code></span></pre>


<p>dataTransferオブジェクトに生えているfiles属性は <strong>Fileオブジェクト</strong> のコレクション（FileList）になっています。 FileListはArrayライクなオブジェクトなので、$.each 等を使って回してみましょう。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">$.each(files, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">file</span>)</span>{
    ...
});
</code></span></pre>


<h3 class="wp-block-heading">File と FileReader</h3>



<p>Fileオブジェクトに生えている <strong>type</strong> という属性でファイルの情報を調べます。 type にはブラウザが分かる範囲で MIME Type を格納してくれているので、 それを使ってテキストなのか画像なのかをものすごくざっくりと判別してみます。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">var</span> type = <span class="hljs-regexp">/^text\//</span>.test(file.type) ? <span class="hljs-string">"text"</span>
    : <span class="hljs-regexp">/^image\//</span>.test(file.type) ? <span class="hljs-string">"image"</span>
    : <span class="hljs-literal">null</span>;

<span class="hljs-keyword">if</span>(! type){
    <span class="hljs-comment">// ファイルタイプがわからない場合はテキストで良いか確認してみる</span>
    <span class="hljs-keyword">if</span>(! <span class="hljs-built_in">window</span>.confirm(file.name + <span class="hljs-string">"はよくわからないファイルですがテキストとして開きますか？"</span>)){
        <span class="hljs-keyword">return</span>;
    }
    type = <span class="hljs-string">"text"</span>;
}
</code></span></pre>


<p>ファイルの中身を読み込むには、 <strong>FileReader</strong> を使用します。 FileReader にはデータを読み込む為のメソッドが幾つか用意されていますが、 今回使うのはテキストとして読み込む <strong>readAsText</strong> と、dataURLとして読み込む <strong>readAsDataURL</strong> です。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">var</span> reader = <span class="hljs-keyword">new</span> FileReader();
<span class="hljs-keyword">if</span>(type === <span class="hljs-string">"text"</span>){
    reader.onload = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
        $(<span class="hljs-string">"&lt;pre&gt;"</span>).text(reader.result).appendTo(<span class="hljs-string">"body"</span>);
    };
    reader.readAsText(file);
    <span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">if</span>(type === <span class="hljs-string">"image"</span>){
    reader.onload = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
        $(<span class="hljs-string">"&lt;img&gt;"</span>).attr(<span class="hljs-string">"src"</span>, reader.result).appendTo(<span class="hljs-string">"body"</span>);
    };
    reader.readAsDataURL(file);
    <span class="hljs-keyword">return</span>;
}
</code></span></pre>


<p>FileReaderオブジェクトは、まずロードが完了した場合の処理を <strong>onload</strong> で設定しておき、 <strong>readAsXXX</strong> メソッドでファイルの読み込みを実行します。 ロードが完了したのち、テキストの場合はpre要素でラップし、 画像の場合はimg要素の src に Data URI をセットして、body 要素に追加しています。</p>



<h2 class="wp-block-heading">ファイナルコード</h2>



<p>モダンな環境であれば動くと思います。 古い環境で開く可能性がある場合はちゃんと判別して対処してあげましょう。</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">$(<span class="hljs-built_in">window</span>).on(<span class="hljs-string">"drop dragover"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    e.preventDefault();
});

$(<span class="hljs-built_in">document</span>).on(<span class="hljs-string">"drop dragend"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    <span class="hljs-keyword">var</span> files = e.originalEvent.dataTransfer.files;

    $.each(files, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">i, file</span>)</span>{
        <span class="hljs-keyword">var</span> type, reader;

        type = <span class="hljs-regexp">/^text\//</span>.test(file.type) ? <span class="hljs-string">"text"</span>
            : <span class="hljs-regexp">/^image\//</span>.test(file.type) ? <span class="hljs-string">"image"</span>
            : <span class="hljs-literal">null</span>;

        <span class="hljs-keyword">if</span>(! type){
            <span class="hljs-keyword">if</span>(! <span class="hljs-built_in">window</span>.confirm(file.name + <span class="hljs-string">"はよくわからないファイルですがテキストで開きますか？"</span>)){
                <span class="hljs-keyword">return</span>;
            }
            type = <span class="hljs-string">"text"</span>;
        }

        reader = <span class="hljs-keyword">new</span> FileReader();

        <span class="hljs-keyword">if</span>(type === <span class="hljs-string">"text"</span>){
            reader.onload = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
                $(<span class="hljs-string">"&lt;pre&gt;"</span>).text(reader.result).appendTo(<span class="hljs-string">"body"</span>);
            };
            reader.readAsText(file);
            <span class="hljs-keyword">return</span>;
        }

        <span class="hljs-keyword">if</span>(type === <span class="hljs-string">"image"</span>){
            reader.onload = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
                $(<span class="hljs-string">"&lt;img&gt;"</span>).attr(<span class="hljs-string">"src"</span>, reader.result).appendTo(<span class="hljs-string">"body"</span>);
            };
            reader.readAsDataURL(file);
            <span class="hljs-keyword">return</span>;
        }
    });
});
</code></span></pre>


<h2 class="wp-block-heading">参考資料</h2>



<ul class="wp-block-list">
<li><a href="https://developer.mozilla.org/ja/docs/DragDrop/Drag_and_Drop">ドラッグ/ドロップイベント</a></li>



<li><a href="https://developer.mozilla.org/ja/docs/DragDrop/DataTransfer">dataTransferオブジェクト</a></li>



<li><a href="https://developer.mozilla.org/ja/docs/Web/API/File">Fileオブジェクト</a></li>



<li><a href="https://developer.mozilla.org/ja/docs/Web/API/FileReader">FileReaderオブジェクト</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
