QA@IT

iOSのカメラアプリで撮影を行うとSafari上で「問題が起きたため、このWebページを再度読み込みました。」と表示されて、ページの再読み込みが発生し撮影した画像が消えてしまう。

8625 PV

前提・実現したいこと
使用機種:iPad Air 2
iOSバージョン:10.3.2
使用ブラウザ:Safari、Chrome 59

ページの再読み込みが発生しないようにしたい

発生している問題・エラーメッセージ
問題が起きたため、このWebページを再度読み込みました。

試したこと
[1]該当ページを定期的に再読み込み
[2]iPadを定期的に再起動

補足情報(言語/FW/ツール等のバージョンなど)
Javascriptの関数"upload"を複数回(1回~)実行すると、エラーメッセージが表示されてしまいます。
問題が発生するタイミングは不定期で規則性はありません。
1回実行した際に発生することもありますし、何十回実行しても発生しないこともあります。

問題が発生する箇所は決まっており、input fileボタンを押しカメラアプリが起動してシャッターを押した直後です。

読み込み元ソース(言語PHP)


    <!DOCTYPE html>
    <html>
        <head>
            <title></title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <meta http-equiv="Content-Style-Type" content="text/css">
            <link href="./css/gazouTouroku.css" rel="stylesheet" type="text/css" />
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
            <script type="text/javascript" src="./js/utility.js"></script>
            <script type="text/javascript" src="./js/gazouTouroku.js"></script>
        </head>
        <body bgcolor="#ffffee">
            <div class="infomation_label margin_new_item">
                <input type="button" value="閉じる" onClick="window.open('about:blank','_self').close()">
            </div>
            <div class="margin_new_item">
                <span class="font_bold"></span>
            </div>
            <table border="0" cellspacing="0" cellpadding="0" class="list">
                <tr>
                    <th colspan="5"></th>
                </tr>
                <?php
                    for( $i=0; $i<30; $i++ ) {
                ?>
                <tr>
                    <td class="image_view_area valign_top">
                        <div id="line_status_pictures<?php echo $j; ?>">
                            <span class="list_item_bg_color font_type_large">
                                <?php
                                    echo $j;
                                ?>
                            </span>
                            <span class="subject_readme">
                                <?php
                                    if($j == 19) {
                                        echo "****";
                                    } else if($j == 20) {
                                        echo "*****";
                                    }
                                ?>
                            </span><br>
                            <input id="pictures<?php echo $j; ?>" type="file" accept="image/*" size="140" onChange="upload('<?php echo $a; ?>', '<?php echo $j; ?>');"><br>
                            <span id="status_pictures<?php echo $j; ?>"></span>&#32;&#32;
                            <input id="resend<?php echo $j; ?>" type="button" size="140" value="再送信" onClick="upload('<?php echo $a; ?>', '<?php echo $j; ?>');" style="display: none;"><br>
                            <?php
                                echo $imgTag;
                            ?>
                        </div>
                    </td>
                    <?php
                        }
                    ?>
                </tr>
                <?php
                    }
                ?>
            </table>
            <div id="dst"></div>
        </body>
    </html>

定義関数(言語Javascript)


    /**
     * dataURL画像情報からExifのOrientation(回転情報)を取得する
     * @param
     * imgDataURL: 画像データを示すdataURL
     */
    function getOrientation(imgDataURL){
        var byteString = atob(imgDataURL.split(',')[1]);
        var orientation = byteStringToOrientation(byteString);
        return orientation;

        function byteStringToOrientation(img){
            var head = 0;
            var orientation;
            while (1){
                if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 218) {break;}
                if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 216) {
                    head += 2;
                }
                else {
                    var length = img.charCodeAt(head + 2) * 256 + img.charCodeAt(head + 3);
                    var endPoint = head + length + 2;
                    if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 225) {
                        var segment = img.slice(head, endPoint);
                        var bigEndian = segment.charCodeAt(10) == 77;
                        var count;
                        if (bigEndian) {
                            count = segment.charCodeAt(18) * 256 + segment.charCodeAt(19);
                        } else {
                            count = segment.charCodeAt(18) + segment.charCodeAt(19) * 256;
                        }
                        for (i=0; i < count; i++){
                            var field = segment.slice(20 + 12 * i, 32 + 12 * i);
                            if ((bigEndian && field.charCodeAt(1) == 18) || (!bigEndian && field.charCodeAt(0) == 18)) {
                                orientation = bigEndian ? field.charCodeAt(9) : field.charCodeAt(8);
                            }
                        }
                        break;
                    }
                    head = endPoint;
                }
                if (head > img.length){break;}
            }
            return orientation;
        }
    }

    // 画像登録後、非同期で再読み込みするため、画像パスに付与するダミーの日付
    var dummyDate = new Date();

    /**
     * 画像を読み込んでS3へアップロード
     * @param
     * a: *****
     * b: *****
     */
    function upload(a, b) {
        // 画像ファイルを読み込むためのFileReaderオブジェクト
        var reader = new FileReader();
        // 画像サイズを取得するためのImageオブジェクト
        var img = new Image();

        // 二重登録を防止するため登録中のファイル選択、再送信ボタンを無効化
        changeButtonStatus(false, b);
        // 枠内に送信状況を表示
        var sending = {
                frameStatus: '送信中',
                addClass: 'line_status_sending',
                removeClass: 'line_status_done line_status_fail',
                b: b,
                showResend: 'none'
        };
        changeImageStatus(sending);

        // 画像読み込み時に渡すプロパティ
        reader.name = a + "," + b;

        // フォーム画像パラメータ
        var photoParam;

        // Base64 画像データ(元画像)
        var imgSrc;

        // Base64 画像データ(縮小済み画像)
        var Base64Img;

        // 回転情報
        var ori;

        // 画像サイズ
        var width;
        var height;

        // 画像縮小、および画像データ転送
        img.onload = function() {
            console.log("img complete");

            //画像サイズを取得
            width = this.width;
            height = this.height;

            Base64Img = scaleDownImage(img, imgSrc.length, width, height, ori);

            // 送信パラメータ設定
            params = { 
                            action: 'post', 
                            car_id : photoParam[0],
                            img_no : photoParam[1],
                            image_base64 : Base64Img,
                            orientation : ori
                        }

            // Ajaxで画像送信
            $.ajax({
                url: 'send.php',
                type:'post',
                dataType: 'json',
                data: params,
                timeout: 10000,
                cache: false
            // 登録成功時
            }).done(function(data) {
                console.log(data);

                // S3への画像登録成功時
                if(data['is_success'] == true) {
                    // 画像URL、再読み込みするため末尾にダミーの日付を付与
                    var imageUrl = "*****" + data['response']['bucket_name']
                                    + "/images/" + data['response']['img_dir'] + photoParam[0] + "-" + photoParam[1] + ".jpg?" + dummyDate.getTime();
                    // 当該画像のaタグID
                    var imageTag = $("#image" + data['response']['img_no']);
                    // リンク先のURL設定
                    imageTag.attr("href", imageUrl);
                    // 画像パス設定
                    imageTag.html('<img src="' + imageUrl + '" height="120" border="0">');
                    // 枠内に送信状況を表示
                    var sendSuccess = {
                            frameStatus: '送信成功',
                            addClass: 'line_status_done',
                            removeClass: 'line_status_sending',
                            b: b,
                            showResend: 'none'
                    };
                    changeImageStatus(sendSuccess);

                // S3への画像登録失敗時
                } else {
                    var sendFailure = {
                            frameStatus: '登録失敗',
                            addClass: 'line_status_fail',
                            removeClass: 'line_status_sending',
                            b: b,
                            showResend: 'inline'
                    };
                    changeImageStatus(sendFailure);
                }
                // 送信ボタンを有効化
                changeButtonStatus(true, b);

            // 画像送信失敗時
            }).fail(function(jqXHR, textStatus, errorThrown) {
                    var sendFailure = {
                            frameStatus: '登録失敗',
                            addClass: 'line_status_fail',
                            removeClass: 'line_status_sending',
                            b: b,
                            showResend: 'inline'
                    };
                changeImageStatus(sendFailure);
                // 送信ボタンを有効化
                changeButtonStatus(true, b);

            });
        }

        // 撮影画像データ読み込み成功時のイベントハンドラ
        reader.onload = function(e) {
            console.log("reader complete");
            // src属性取得
            imgSrc = e.target.result;

            // *****, *****を分解
            photoParam = e.target.name.split(",");

            //回転情報を取得
            ori = getOrientation(imgSrc);
            // src属性にURLを設定。設定すると即座に非同期のリクエストが飛ぶ
            img.src = imgSrc;
        }

        // 画像ファイルをDataURLとして読み込み
        reader.readAsDataURL($("#pictures" + b)[0].files[0]);
    }

    /**
     * 画像の送信状況(枠色、メッセージ)を表示し、
     * @param
     * stauts: {
     *  frameStatus: 送信状況のメッセージ
     *  addClass: 表示したい送信状況のクラス名
     *  removeClass: 削除したい送信状況のクラス名(複数の場合はスペースで区切る)
     *  b: 画像番号
     *  showResend: 再送信ボタン表示・非表示
     * }
     */
    function changeImageStatus(status) {
        with(status) {
            // 枠内に送信状況のメッセージを表示
            $("#status_pictures" + b).html(frameStatus);
            // 表示したい送信状況のクラス
            $("#line_status_pictures" + b).addClass(addClass);
            // 削除したい送信状況のクラス
            $("#line_status_pictures" + b).removeClass(removeClass);
            // 再送信ボタンの表示・非表示設定
            $("#resend" + b).css("display", showResend);
        }
    }

    /**
     * 「ファイルを選択」ボタン、再送信ボタンの表示・非表示を変更する
     * @param
     * showFlag: 表示フラグ
     * true: 表示、false: 非表示
     * b: 画像番号
     */
    function changeButtonStatus(showFlag, b) {
        // 「ファイルを選択」ボタ
        $("#pictures" + b).prop("disabled", !showFlag);
        // 再送信ボタン
        $("#resend" + b).prop("disabled", !showFlag);
    }

    /**
     * 縦横比を判断して縮小
     * @param
     * image: Imageオブジェクト
     * base64length: データサイズ
     * width: 画像サイズ(幅)
     * height: 画像サイズ(高さ)
     * orientation: 画像回転情報 
     */
    function scaleDownImage(image, base64length , width, height, orientation) { 
        //回転情報が含まれていない
        if(orientation==undefined){
            console.log("PC");

            //高さより幅が大きい画像
            if(height < width ){
                var scaleWidth = 960;
                var scaleHeight = 960 / width * height;
            }
            //幅より高さが大きい画像
            else {
                var scaleWidth = 960;
                var scaleHeight = 960 / height * width;
            }
        }
        //回転情報が含まれている
        else {
            console.log("iPad");

            //高さより幅が大きい画像
            if(height < width ){
                var scaleWidth = 960;
                var scaleHeight = 960 / width * height;
            }
            //幅より高さが大きい画像
            else {
                var scaleWidth = 960 / height * width;
                var scaleHeight = 960;
            }
        }

        if(1398101 < base64length) {
            //canvas生成
            var canvas = $('<canvas></canvas>');
            var context = canvas[0].getContext('2d');
            canvas[0].width = Math.floor(scaleWidth);
            canvas[0].height = Math.floor(scaleHeight);

            //画像縮小
            context.drawImage(image, 0, 0, image.width, image.height, 0, 0, scaleWidth, scaleHeight);
        }
        else {
            //canvas生成
            var canvas = $('<canvas></canvas>');
            var context = canvas[0].getContext('2d');
            canvas[0].width = image.width;
            canvas[0].height = image.height;

            //画像縮小
            context.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width, image.height);
        }

        return canvas[0].toDataURL();
    }

ウォッチ

この質問への回答やコメントをメールでお知らせします。