質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

iOSで画像ファイルのアップロードを行うとエラーが発生する

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 4,858

kariya

score 75

iOSで画像ファイルのアップロードを行うとエラーが発生する

HTML,JavaScript,クラシックASPでiOS向けWebアプリを開発しています。
iPhone等で撮影、または画像ファイルを選択し、ファイルサイズを縮小してwebサーバーにアップロードする仕組みを作っています。
ファイルサイズの縮小には、JSを用いてcanvasタグに描画しており、canvasのimageをbase64urlへエンコーディングした文字列をサーバーにPOSTさせています。
アップロードファイルの容量は2~3Mbyte程度で、最大で2つのファイルを指定できるようにしています。

PCでもiOSでも想定通りに動作しますが、iOSでは「このWebページで問題が起きたため、再度読み込まれました。」のメッセージが画面上部に表示され、
さらに画面中央にモーダルダイアログで「本当にこのフォームを再送信しますか?」とのメッセージが表示されます。

このメッセージの原因や解消方法があればご教授いただきたいです。

発生している問題・エラーメッセージ

このWebページで問題が起きたため、再度読み込まれました。

該当のソースコード

以下のソースは抜粋です。

<input type="file" accept="image/*" capture="camera" name="uploadFile" id="uploadFile" onchange="dispThumbnail()">
<canvas id="dispPhoto" name="dispPhoto" width="480" height="360"></canvas>
function dispThumbnail(){
    var select_file = document.getElementById("uploadFile");
    var canvas = document.getElementById("dispPhoto");
    var file = select_file.files;
    var reader = new FileReader();
    //dataURL形式でファイルを読み込む
    reader.readAsDataURL(file[0]);
    //ファイルの読込が終了した時の処理
    reader.onload = function(){
        readDrawImg(reader, canvas, 0, 0);
    }
}
function readDrawImg(reader, canvas, x, y){
    var img = readImg(reader);
    var canvasDefW = canvas.width;    // canvasの初期幅
    img.onload = function(){
        var w = img.width;
        var h = img.height;
        // 横幅を基準としてリサイズする
        var resize = resizeWidthHeight(canvasDefW, w, h);
        drawImgOnCav(canvas, img, x, y, resize.w, resize.h);
        // CanvasImageのBASE64URIへの変換
        document.getElementById("base64area").value = canvas.toDataURL("image/png");
    }
}
//ファイルの読込が終了した時の処理
function readImg(reader){
    //ファイル読み取り後の処理
    var result_dataURL = reader.result;
    var img = new Image();
    img.src = result_dataURL;
    return img;
}
//キャンバスにImageを表示
function drawImgOnCav(canvas, img, x, y, w, h) {
    var ctx = canvas.getContext("2d");
    canvas.width = w;
    canvas.height = h;
    ctx.drawImage(img, x, y, w, h);
}
// リサイズ後のwidth, heightを求める
function resizeWidthHeight(target_length_px, w0, h0){
    //リサイズの必要がなければ元のwidth, heightを返す
    if(w0 <= target_length_px){
        return{
            flag: false,
            w: w0,
            h: h0
        };
    }
    // 横幅を基準としたリサイズの計算
    var w1;
    var h1;
    w1 = target_length_px;
    h1 = h0 * target_length_px / w0;
    return {
        flag: true,
        w: w1,
        h: h1
    };
}
Dim s_cntTotal
Dim s_getBinary
Dim s_objBasp21
Dim s_strBase64
Dim s_result

s_cntTotal = Request.TotalBytes
s_getBinary = Request.BinaryRead(s_cntTotal)
SET s_objBasp21 = server.createobject("basp21")

s_strBase64 = s_objBasp21.Form(s_getBinary, "base64area")
s_result = ImportCanvas(s_strSaveMapFilePass, s_strBase64)

Function ImportCanvas(param_strFilePass, param_strBase64)
    Const adTypebinary = 1    ' バイナリデータ
    Const adTypeText = 2    ' テキストデータ

    Dim stream, xmldom, node
    Dim strBase64
    Set xmldom = Server.CreateObject("Microsoft.XMLDOM")
    Set node = xmldom.CreateElement("base64")
    node.DataType = "bin.base64"

    strBase64 = Replace(param_strBase64, "data:image/png;base64,","") 'Base64の文字列を渡す
    If InStr(strBase64, "data:image/") <> 0 Then
        strBase64 = Replace(param_strBase64, "data:image/jpeg;base64,","") 'Base64の文字列を渡す
    End If
    node.text = strBase64
    Set stream = Server.CreateObject("ADODB.Stream")
    stream.Type = adTypeBinary
    stream.Open
    stream.write node.NodeTypedValue
    stream.saveToFile param_strFilePass, 2 'ファイルを作成
    stream.Close
    Set stream = Nothing

    Set node = Nothing
    Set xmldom = Nothing

    ImportCanvas = 0
End Function

試したこと

  • IISの設定「最大要求エンティティボディ制限」の関係かと思いましたが、確認したところ33Mbyteまでの設定になっていたので問題ないようです。
  • input要素で選択する元ファイルの容量が小さい(50Kbyte)場合、上記のエラーは発生しませんでした。65Kbyteであれば、エラーが発生しました。

補足情報(言語/FW/ツール等のバージョンなど)

実行端末:iOS10以上

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

+1

(一応)解決しました

function readDrawImg(reader, canvas, x, y){
    var img = readImg(reader);
    var canvasDefW = canvas.width;    // canvasの初期幅
    img.onload = function(){
        var w = img.width;
        var h = img.height;
        // 横幅を基準としてリサイズする
        var resize = resizeWidthHeight(canvasDefW, w, h);
        drawImgOnCav(canvas, img, x, y, resize.w, resize.h);
        // CanvasImageのBASE64URIへの変換
        document.getElementById("base64area").value = canvas.toDataURL("image/png");
    }
}


上記のソースの最終行を

        // CanvasImageのBASE64URIへの変換
        document.getElementById("base64area").value = canvas.toDataURL("image/jpeg");


と変更したところ、選択するファイルサイズに関わらずエラーが発生しなくなりました。
とは言っても、ファイルサイズは高々2~3Mbyteくらいでしか確認していませんが。

恐らくbase64のエンコード、デコード処理あたりに原因があるようですが、詳しい原因については自分の力量では解明できませんでした。

解決としていますが、後学のため、より詳しい原因について分かる方がいらっしゃればコメントいただけると幸いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る