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

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

ただいまの
回答率

90.45%

  • Ajax

    1357questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

jquery ajax通信での変数データと画像データの同時送信

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,943

1ss411

score 11

ajax通信についての質問をさせていただきます。
変数データのみの送信はできるのですが、画像の送信も一緒にするとなった時にどうしても送信ができないです。

今のところ、ajax通信の中のalert文が表示されないです。

以下が実行したいプログラムです。

var pictureSource;   // 写真ソース 
var destinationType; // 戻り値のフォーマット 

document.addEventListener("deviceready",onDeviceReady,false); 
function onDeviceReady() { 
        pictureSource=navigator.camera.PictureSourceType; 
        destinationType=navigator.camera.DestinationType; 
} 

// 撮影
function capturePhoto() { 
        // 撮影した写真をBase64形式の文字列として取得 
        navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50 }); 
} 

// 
function onPhotoDataSuccess(imageData) {
       var byteString = atob(imageData);
       var ia = new Uint8Array(byteString.length);
       for (var i = 0, l = byteString.length; i < l; i++) {
           ia[i] = byteString.charCodeAt(i);
       }
       var picBlob = new Blob([ia], 'image/jpeg'); // MIMETYPEは画像に合わせる 
} 

// 送信ボタンを押した後の処理
function onButtonClick() {

    var formData = new FormData();
       formData.append('test1', id);
       formData.append('test2', title);
       formData.append('test3', latitude);
       formData.append('test4', longitude);
    formData.append('pic', picBlob); //ここを除けば正常に動きます。

        //データベースへ送信
        $.ajax({
            url: "soshin.php",
            type:"POST",
       data: formData,
            success: function(data){
                alert(data);
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
                alert("ng");
            }
        });
}
<?php

//エラー表示
ini_set( 'display_errors', 1 );

//DB接続PHP呼び出し
include 'MySQL.php';

//取得した画像の名前を現在のUnixタイムスタンプに置き換えるための準備
$time = time();
$timerename = $time.$_POST['test2'];
$timename = $timerename.'.jpg';

//写真の保存
if (is_uploaded_file($_FILES['pic']['tmp_name'])) {

    $tmp_path = $_FILES['pic']['tmp_name'];
    $target_path = '/image/'.$timename; //画像保存ディレクトリ


    //一時保存画像を保存ディレクトリに移動
    if(move_uploaded_file($tmp_path,$target_path)){

        //保存成功
        echo $_FILES["pic"]["name"] . "をアップロードしました。";

    } else {

        //ファイルを持ってこれたが、アップロードできなかった場合
            echo "ファイルをアップロードできません。";

    } else {
          echo "ファイルが選択されていません。";
    }
}

$data1 = $_POST['test1'];
$data2 = $_POST['test2'];
$data3 = $_POST['test3'];
$data4 = $_POST['test4'];

//INSERT文
$sql = $db->prepare("insert into test_1(title, latitude, longitude)
        values(:title, :latitude, :longitude)");
$sql->bindParam(':title',$data2, PDO::PARAM_STR);
$sql->bindParam(':latitude',$data3, PDO::PARAM_STR);
$sql->bindParam(':longitude',$data4, PDO::PARAM_STR);
$sql->execute();

$sql = 'select * from test_1;';
    $stmt = $db->query($sql);
    if(!stmt){
        $err = $db->errorInfo();
        die('SELECT 失敗:' . $err[2]);
    }
    while($data=$stmt->fetch(PDO::FETCH_ASSOC)){
        print_r($data);
    } 

//PDO接続終了
unset($db);

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

+1

jQuery.ajaxFormDataを送信したい場合、以下の2つの設定が必要となります(MDN)。

  • dataにはFormDataだけを指定する(他のパラメーターも全てFormDataに設定して下さい)。
  • processData: false, contentType: falseを指定する(jQuery内の処理をバイパスする必要があります)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/12/21 22:36

    お答えいただきありがとうございます。
    上記の二点、参考にさせていただきます。

    キャンセル

+1

すでに@maisumakunさんがおっしゃっている部分の説明は割愛しますが、

そのほかに気づいた点として、base64のまま送信しようとしている点です。
base64はご存知かと思いますが文字列ですので、ファイルとして、つまりmultipart展開されず、単にパラメータの値として送信されると思います。
そうなると、php側で

 $_FILES["pic"]


として取得することはできません。
ですので、取得したbase64の画像データをBlob型に変換してからformDataに追加し送信すれば、
ファイルとして送信することができ、$_FILES['pic']で受け取れると思います。

var picBlob;

navigator.camera.getPicture(onPhotoDataSucces, onFail, {quality: 50});

function onPhotoDataSuccess(imageData) {
    var byteString = atob();
    var ia = new Uint8Array(byteString.length);
    for (var i = 0, l = byteString.length; i < l; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    picBlob = new Blob([ab], 'image/jpeg'); // MIMETYPEは画像に合わせる
}

function onButtonClick() {
    var formData = new FormData();
    formData.add('test1', id);
    formData.add('test2', title)
    formData.add('test3', latitude);
    formData.add('test4', longitude);
    formData.add('pic', picBlob);

    //データベースへ送信
    $.ajax({
        url: "soshin.php",
        type: "POST",
        data: formData,
        contentType: false,
        processData: false, 
        success: function(data) {
            alert(data);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert("ng");
        }
    });
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/12/21 22:33

    お答えいただきありがとうございます。
    プログラムを動かしたところ、
    formData.append('pic' , picBlob);
    のところがおかしいことがわかりました。
    カメラ撮影後のatob()のところではないかと思っているところです。()の中には、何かの記述が必要な気がしてならないです。もし、何かわかりましたらお教えください。

    キャンセル

  • 2016/12/21 22:34

    あ、ごめんなさい、
    ```js
    var byteString = atob(imageData);
    ```
    です。

    キャンセル

  • 2016/12/21 23:05

    早い返信ありがとうございます。
    指摘していただいたところを直したのですが、変わりませんでした。
    picBlobがおかしいとは思うのですが、、

    キャンセル

  • 2016/12/21 23:10

    picBlob = new Blob([ab], 'image/jpeg');
    のところ
    picBlob = new Blob([ia], 'image/jpeg');
    間違いでした。ごめんなさい。
    あと、ChromeのdevToolsなどで送信されているデータを確認してみてはいかがでしょう。

    キャンセル

  • 2016/12/21 23:29

    abをiaに直しましたが、うまくいきませんでした。
    それとajax通信が行われていないことが分かりました。
    もし、他に気づく点があったら教えていただけるとありがたいです。

    キャンセル

  • 2016/12/21 23:38 編集

    ごめんなさい。これ以上のことはわかりません。
    ただ、ほかに気づいた点としては、私はCordova(と思う)使ったことがないからわからないのですが、
    ググってみたところgetPicture()の戻り値(onPhotoDataSuccessの引数)はbase64のみの文字列を返すようですが、CordovaアップデートでDataURLスキーム("data:image/png;base64,~")で返すようになったのでしょうか。
    修正前の記載されたコードに、getPicture()の戻り値をそのままimage.srcに設定してましたけど画像は表示されてるのでしょうか?

    キャンセル

  • 2016/12/21 23:50

    画像の表示はしています。
    <img style="display:none;width:180px;height:180px;" id="smallImage" src="" />
    このようにhtmlの部分に記述して表示させています。

    以下はscript部分です。
    var smallImage = document.getElementById('smallImage');
    smallImage.style.display = 'block';
    smallImage.src = imageData

    キャンセル

  • 2016/12/21 23:57

    となると,imageDataには”data:image/png;base64,”といった文字列から始まる値が渡されいると思いますので、確認してみてください。
    もし"data:~"で始まる文字列だった場合は、atob()のところは以下のように修正する必要があります。
    var byteString = atob(imageData.split(',')[1]);

    キャンセル

  • 2016/12/22 16:09

    imageDataの値を確認しました。
    file:///var/mobile/Containers/Data/Application/4A8100C4-9E3C-49E6-AE73-F6E0F474B3EC/tmp/cdr_photo_040.jpg

    といったものが入っていました。

    キャンセル

  • 2016/12/22 17:50

    それは、base64ではなくファイルURIになります。
    navigator.camera.getPicture()を実行するとき、qualityのみ指定して実行しているからで、optionsでdesitinationTypeを指定していなければdestinationTypeはデフォルトのCamera.DestinationType.FILE_URIで実行します。
    ですので、destinationTypeも指定して実行してみてください。
    navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.DATA_URL });

    キャンセル

  • 2016/12/22 18:54

    destinationTypeを設定して、imageDataの値を確認したところ、とても数え切れないほどの英数字の文字列が出てました。
    それと、実行を試みたのですが、やはりajax通信の手前で止まってしまいます。

    キャンセル

  • 2016/12/22 18:58 編集

    具体的にどこで止まっているのでしょうか?(どんなエラーが発生しているのか)

    キャンセル

  • 2016/12/22 19:34

    formData.append('pic', picBlob);
    の前に適当にalert("ok")を記述したら、表示はするのですが、その文の後にalert("ok")を記述したら表示されないです。

    キャンセル

  • 2016/12/27 18:25

    alert文は表示されるようになりました。
    後は、ajax通信でエラーが返されるので、そこが分からないところです。。。

    キャンセル

  • 2016/12/28 09:17

    エラーが返されたときは、そのエラーをこちらに書くようにしてください。

    キャンセル

0

HTMLについてでよろしいですよね?
送りたいファイルの指定方法とトリガーはどうなっていますか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/12/21 22:38

    今現在、turbgraphicsさんの方法を参考にさせていただいている状況です。

    キャンセル

0

まず、jQuery.ajax の data ですが、それに設定するのは、

(1) GET 要求(クエリ文字列としてデータを送信)の場合は JavaScript オブジェクト 
(2) POST 要求(コンテンツとしてデータを送信)の場合は JSON 文字列

にする必要があるはずです。詳しくは以下の記事を見てください。質問者さんのコードでは POST で JavaScript オブジェクトを設定しているように見えます。

jQuery.ajax の data の型
http://surferonwww.info/BlogEngine/post/2015/10/05/what-must-be-set-to-data-option-in-jquery-ajax.aspx

そして、formData に設定するのを Data url 形式(画像データの文字列)とし、サーバー側ではそれを受けて元のバイト列に変換するという方法はいかがでしょう?

以下の記事の応用でできるのではないかと思います。検討ください。

canvas の画像をアップロード
http://surferonwww.info/BlogEngine/post/2015/07/02/upload-image-drawn-on-html5-canvas.aspx

Data url 形式は BASE64 でエンコードされるので、バイナリ形式よりサイズが約 1.3 倍大きくなってしまうのがなんですが。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/12/21 22:35

    お答えいただきありがとうございます。
    monacaで行っているのですが、値の送信に関しては、javascriptでPOSTでまったく問題がなく動くので、よく分からないです。
    いろいろと調べさせていただきます。

    キャンセル

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

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

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

  • Ajax

    1357questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。