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

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

ただいまの
回答率

89.71%

android端末からCSVファイルをPHPにアップロード

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 84

karetama

score 6

前提・実現したいこと

android端末からCSVファイルをPHPに POSTしてファイルを保存したいのですが、うまくPHP側で受け取ることができていません。Wiresharkを使い通信を覗いたところandroi端末からPHP側のサーバには通信できていることがわかったので、受け取るkeyを設定していないからなのか?と考えております。

いろいろ調べてみるとリクエストボディの書き込みをしないといけないぽい事が分かったのですがどのように書けばいいかわかりません。JSON文字列とかもよくわかりません。

PHP側でやる場合はフォームの作成で
<input type="text" name="text1">
と書き
フォームの取得で
<?php
echo($_POST['text1']);
?>
と書けばフォームから値がtaxt1に書き込まれ送信した際データが取得できるんですが android側でフォームの処理を行うにはどうすればよいのでしょうか。
keyは'uploaded_file'にしようと考えております。

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

Notice: Undefined index: uploaded_file in /var/www/html/UploadToServer.php on line 3

Notice: Undefined index: uploaded_file in /var/www/html/UploadToServer.php on line 4
エラーが発生しました。

該当のソースコード(1)

android(java)ファイル
//androidにあるファイルをサーバにアップロードします
    public int uploadFile(final String selectedFilePath) {

        int serverResponseCode = 0;

        HttpURLConnection connection ;
       // DataOutputStream dataOutputStream ;//アプリケーションはプリミティブ型のJavaデータを移植性のある形で出力ストリームに書き込むことができます。アプリケーションはデータ入力ストリームを使ってデータを読み戻すことができます。
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";


        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1 * 1024 * 1024;
        File selectedFile = new File(selectedFilePath);


        String[] parts = selectedFilePath.split("/");
        final String fileName = parts[parts.length - 1];

        if (!selectedFile.isFile()) {
            dialog.dismiss();

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tvFileName.setText("Source File Doesn't Exist: " + selectedFilePath);
                }
            });
            return 0;
        } else {
            try {
                FileInputStream fileInputStream = new FileInputStream(selectedFile); //CSVデータをストリームに書き込むバイト数を取得
                DataOutputStream dataOutputStream ; //アプリケーションはプリミティブ型の Java データを移植性のある形で出力ストリームに書き込むことができます
                URL url = new URL(SERVER_URL);

                connection = (HttpURLConnection) url.openConnection();
                connection.setDoInput(true);//入力を許可
                connection.setDoOutput(true);//出力を許可する
                connection.setUseCaches(false);//キャッシュされたコピーを使用しないでください
                connection.setRequestMethod("POST");
                connection.setRequestProperty("ENCTYPE", "multipart/form-data");//データをマルチパート形式で送信します(複数の種類のデータを持つ)
                connection.setRequestProperty("Connection", "Keep-Alive");  //コスト削減方法
                connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);//ファイルの種類を表す情報が入ってるよ
                connection.setRequestProperty("uploaded_file", selectedFilePath);


                //新しいデータ出力ストリームの作成
                dataOutputStream = new DataOutputStream(connection.getOutputStream());

                //バイトをデータ出力ストリームに書き込む
                dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
                dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
                        + selectedFilePath + "\"" + lineEnd);
                dataOutputStream.writeBytes(lineEnd);
                dataOutputStream.flush();

                //コンピューターでデータを一時的に記憶する場所
                bytesAvailable = fileInputStream.available();
                //バッファサイズを使用可能な最小バイトまたは1 M​​Bとして選択
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                // bufferSizeのサイズのバイト配列としてバッファを設定します
                buffer = new byte[bufferSize];

                // FileInputStreamからバイトを読み取ります(バッファーの0番目のインデックスからbuffersizeまで)
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                // bytesRead = -1になるまでループを繰り返します。つまり、読み取るバイトがなくなる

                while (bytesRead > 0) {
                    //入力ストリームから読み取ったバイトを書き込みます
                    dataOutputStream.write(buffer, 0, bufferSize);

                    bytesAvailable = fileInputStream.available();


                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }

                dataOutputStream.writeBytes(lineEnd);
                dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);


                //get.ResponsCode()  HTTP 応答メッセージから状態コードを取得します
                serverResponseCode = connection.getResponseCode();
                String serverResponseMessage = connection.getResponseMessage();

                Log.i(TAG, "Server Response is: " + serverResponseMessage + ": " + serverResponseCode);

                //応答コード200は、サーバーステータスがOK
                if (serverResponseCode == 200) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tvFileName.setText("ファイルの Upload が成功しました.\n\n 送信先 \n\n" + "http://192.168.2.117\n\n" + fileName);
                        }
                    });
                }

                //入力ストリームと出力ストリームを閉じます
                fileInputStream.close();
                dataOutputStream.flush();
                dataOutputStream.close();


            } catch (FileNotFoundException e) {
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "File Not Found", Toast.LENGTH_SHORT).show();
                    }
                });
            } catch (MalformedURLException e) {
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "URL error!", Toast.LENGTH_SHORT).show();

            } catch (IOException e) {
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "Cannot Read/Write File!", Toast.LENGTH_SHORT).show();
            }
            dialog.dismiss();
            return serverResponseCode;
        }

    }
}

該当のソースコード(2)

<?php
$target_dir  = "./upfile/";
$target_path = $target_dir . basename( $_FILES['uploaded_file']['name']);
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $target_path)) {
 echo "The file ".  basename( $_FILES['uploaded_file']['name']).
 " アップロードができました";
} else{
 echo "エラーが発生しました。";
}
?>
~    

試したこと

wiresharkで通信を覗いたところ android端末と自サーバとの通信はできていた。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2020/01/15 08:54

    >Notice: Undefined index: uploaded_file

    このNoticeはどこでどのようにして得られたのでしょうか。

    キャンセル

  • karetama

    2020/01/15 09:22

    質問ありがとうございます。android側からデータを送信した後、PCのほうで用意して置いたPHPのファイルを開くとそのようなエラーがおきていました。

    キャンセル

  • m.ts10806

    2020/01/15 09:27

    それはそうなりますね。

    キャンセル

  • karetama

    2020/01/15 09:34

    どのようにすればよいのでしょうか...質問攻めで申し訳ございません。

    キャンセル

回答 1

checkベストアンサー

0

android側からデータを送信した後、PCのほうで用意して置いたPHPのファイルを開くとそのようなエラーがおきていました。 

androidでもWebViewのような形で直接画面遷移が発生しないものでしたら、それぞれは独立したアプリケーションです。
「PHPのファイルを開く」ということはあくまでURLをブラウザから実行したに過ぎず、「androidからのリクエスト」ではなく「実行したブラウザからのGETリクエスト」になります。

他の媒体からPHPなどを実行する場合はAPIとしての実行になります。
Androidの方に精通しているわけではありませんが、コードからHttpURLConnectionを確立し、リクエスト情報を設定し、URLに対して送信して、レスポンスを得ているように思います。

確認すべきはandroidに返ってきたレスポンス情報になります。
基本的にはPHP側で「出力」された情報が返ってきているはずです。
echoが書かれているのでそのechoは返ってきてると思います。
ファイルアップロードはジャッカン敷居が高いので、ひとまず何かしらの文字列を送信して、その文字列に別の文字列を追加して出力し、Android側でレスポンスを確認するところから始めてみてはいかがでしょうか。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/01/15 10:47

    直接画面遷移が発生していたら確かにPOSTして反映されますね...
    すごく分かりやすいです。ありがとうございます。そうなってくるとプログラムの全体的な話になってきますね..1つ1つこなしていこうと思います。ご回答ありがとうございました。

    キャンセル

  • 2020/01/15 10:59

    ちなみに考え方はAjaxと同じです。
    PHP側は誰からリクエストがあるとかは知らない状態なので、送られたリクエストを受け取り、所定の処理をして、送られてきた元に返すだけとなります。

    キャンセル

  • 2020/01/15 11:12

    quearyを送ってandroid端末であることをまず教える感じですかね...イメージが少しずつわいてきました。
    ありがとうございます。

    キャンセル

  • 2020/01/15 12:19 編集

    いえ、特に要件にないのでしたら教える必要はないです。
    どこからのアクセスが来たとかログとりたいときに端末情報をPOSTしてその情報を保存するように作ってください。
    くり返しますがAPIは受け取ったリクエストを以て所定の処理を行い、送ってきた先に返すだけです。
    先の「端末情報を~」もPHP側はどこからだれが送ったか知る術にはなりません。開発者側の都合で送って受け取ってるだけです。

    キャンセル

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

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