input[type=file]で投稿画像を即時表示する際のメモ

input[type=file]使って投稿画像を表示する時、
大抵の場合はFileReaderオブジェクトのreadAsDataURLメソッドを使うサンプルをよく見かけるけど、
Android4.0だと動作が不安定だった。

```js
$(function(){
    
    var $input = $('#js-input'),
        $result = $('#js-result');
    
    $input.on('change', function(e){
        var file = e.target.files[0];
        if (!file) {
            return;
        };
        var filereader = new FileReader();
        filereader.onload = function(e){
            var url = e.target.result,
                $img = $('<img>').on('load error', function(){
                    $result.append(this);
                }).attr('src', url);
            alert(url);
        };
        filereader.readAsDataURL(file);
    });
    
});
```

何とかならないものかと調べてみると、
window.URL.createObjectURLを使いつつ、
フォールバックとしてreadAsDataURLを使うと良いみたい。

しかもreadAsDataURLだとクソでかいbase64文字列が生成されるので大量にメモリを食うけど、
window.URL.createObjectURLだとそうはならないらしい（まだ未確認。

下記だとAndroid4.0で不安定。

```js
$(function(){
    
    var $input = $('#js-input'),
        $result = $('#js-result');
    
    $input.on('change', function(e){
        var file = e.target.files[0];
        if (!file) {
            return;
        };
        var url = window.URL.createObjectURL(file),
            $img = $('<img>').on('load error', function(){
                $result.append(this);
            }).attr('src', url);
        alert(url);
    });
    
});
```

下記はAndroid4.0でも安定。

```js
var createObjectURL = (window.URL && window.URL.createObjectURL) ? function(file) {
    return window.URL.createObjectURL(file);
} : (window.webkitURL && window.webkitURL.createObjectURL) ? function(file) {
    return window.webkitURL.createObjectURL(file);
} : undefined;

$(function(){
    
    var $input = $('#js-input'),
        $result = $('#js-result');
    
    $input.on('change', function(e){
        var file = e.target.files[0];
        if (!file) {
            return;
        };
        var filereader = new FileReader();
        filereader.onload = function(e){
            var url = createObjectURL
                ? createObjectURL(file)
                : e.target.result,
                $img = $('<img>').on('load error', function(){
                    $result.append(this);
                }).attr('src', url);
            alert(url);
        };
        filereader.readAsDataURL(file);
    });
    
});
```

最高じゃないすか。。

## 参考URL

[window.URL.createObjectURL - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/URL/createObjectURL)
[createObjectURLがすごい件 - プログラムモグモグ](http://itchyny.hatenablog.com/entry/20111119/1321710966)
[createObjectURLとは何か？ - NullPointer's Blog](http://paulownia.hatenablog.com/entry/20120506/1336324323)
[モバイルブラウザでの画像アップロードについて覚え書き ::ハブろぐ](https://havelog.ayumusato.com/develop/others/e567-mobile_image_resize.html)
[FileReader利用時のメモリ増減パターンをちょっと調べてみた ::ハブろぐ](https://havelog.ayumusato.com/develop/javascript/e303-filereader_memory_gc.html)

ちなみにiPhoneで撮影した画像を表示しようとすると、
jpegに埋め込まれたexif情報のorientationを元に、
勝手に回転させられて表示が変になるので、
下記のような対応が別途必要になる。

[ImageMagickでjpegの縦横(exifのOrientation)情報を元に画像を回転する - lxyuma BLOG](http://lxyuma.hatenablog.com/entry/2013/12/07/095742)
[javascript - extract exif orientation data from image - Stack Overflow](https://stackoverflow.com/questions/14270574/extract-exif-orientation-data-from-image)
https://github.com/jseidelin/exif-js/blob/master/exif.js
[JavascriptでJPEG画像からEXIFのOrientation情報のみを取得する | egashira.jp](https://egashira.jp/obtain-orientation-from-jpeg-exif)