Android HttpURLConnection无法发送帖子数据

时间:2016-12-06 06:16:33

标签: java php android http post

实际上有几十个Stack Overflow条目都带有这样的标题,然而在所有这些条目中,这个问题似乎并不适用,示例解决方案看起来就像我的代码。问题是:为什么以下似乎不通过帖子将数据发送到网页。

预期行为:按下活动中的“测试”按钮会导致以下输出:

{timestamp}/com.example.test D/Test: url: http://data.cubscout.local/enter_game_design
{timestamp}/com.example.test D/Test: json sent
{timestamp}/com.example.test D/Test: http response code: 200
{timestamp}/com.example.test D/Test: {"test_value":"test"}
{timestamp}/com.example.test D/Test: result read
在logcat中使用

,并在页面的错误日志中打印{"test_value":"test"}

实际行为:按下活动中的“测试”按钮会导致以下输出:

{timestamp}/com.example.test D/Test: url: http://data.cubscout.local/enter_game_design
{timestamp}/com.example.test D/Test: json sent
{timestamp}/com.example.test D/Test: http response code: 200
{timestamp}/com.example.test D/Test: result read
在logcat中

并且一行打印到只是时间戳的网页的错误日志

编辑:请注意,使用curl之类的命令发送数据会导致预期的行为。例如。 curl -i -H "Accept: application/json" -X POST -d {"test_value":"test"} http://da/enter_game_design/ 导致{"test_value":"test"}被curl接收并打印在日志中这使我得出结论,即使接收服务器响应的代码有问题,代码也会在第一次发送地方坏了。

编辑2:我已经测试Log.d("Test", IOUtils.toString(connection.getInputStream()));确实会通过将网址更改为其他网页来正确地将输出打印到日志

MainActivity.java:

package com.example.test;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

/**
 * Created by trevor on 12/5/16.
 */

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button testButton = (Button)findViewById(R.id.button);
        testButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new AsyncUploadTest().execute();
            }
        });
    }
    private class AsyncUploadTest extends AsyncTask<Void,Void,Boolean>
    {
        @Override
        protected Boolean doInBackground(Void... v) {
            try {
                URL url = new URL("http://data.cubscout.local/enter_game_design");

                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                Log.d("Test","url: "+connection.getURL());

                connection.setUseCaches(false);
                connection.setDoOutput(true);
                connection.setDoInput(true);

                connection.setRequestMethod("POST");
                connection.setRequestProperty("Connection", "Keep-Alive");
                connection.setRequestProperty("Cache-Control", "no-cache");
                connection.setRequestProperty("Content-Type","application/json;charset=utf-8");
                connection.setRequestProperty("Accept","application/json");

                OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
                writer.write("{\"test_value\":\"test\"}");
                writer.flush();
                writer.close();

                Log.d("Test","json sent");

                int httpResult = connection.getResponseCode();
                Log.d("Test","http response code: "+httpResult);
                if(httpResult == HttpURLConnection.HTTP_OK)
                {
                    Log.d("Test", IOUtils.toString(connection.getInputStream()));
                    Log.d("Test", "result read");
                }

            } catch (MalformedURLException e) {
                Log.e("Test","exception while sending data to server",e);
            } catch (ProtocolException e) {
                Log.e("Test","exception while sending data to server",e);
            } catch (IOException e) {
                Log.e("Test","exception while sending data to server",e);
            }
            return true;
        }
    }
}

activity_main.xml(布局文件)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:text="Test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button" />
</LinearLayout>

的AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="Test">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

正在访问的网页的php脚本

<?php
    $inputString = file_get_contents("php://input");
    error_log($inputString);
    echo $inputString;
?>

2 个答案:

答案 0 :(得分:0)

当响应代码为HTTP_OK时,您可以获得响应。

您的代码的问题在于它不是从服务器获取实际对象,它只是获取响应代码...用于获取实际数据/对象,您需要创建一个缓冲读取器并获取输入流如下。

试试这个:

int httpResult = connection.getResponseCode();
Log.d("Test","http response code: "+httpResult);

if(httpResult == HttpURLConnection.HTTP_OK) {
    Log.d("Test",IOUtils.toString(connection.getInputStream()));
    Log.d("Test", "result read");

    //get response
    BufferedReader in = new BufferedReader(
        new InputStreamReader(connection.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }

    in.close();

    //print result
    System.out.println(response.toString());
}

您可能需要使用json转换器将响应字符串转换为json。

答案 1 :(得分:0)

首次连接HttpURLConnection时,响应代码为301 moved permanently。这是因为网址缺少结尾/HttpURLConnection透明地重新建立与第一个连接提供的URL的连接,但不重新发送帖子数据。在这种情况下修复问题很简单:在我自己中添加斜杠。鉴于HttpURLConnection的行为,我建议您通过执行以下操作自行处理POST请求的重定向:

try {
    URL url = new URL("http://data.cubscout.local/enter_game_design");
    boolean redirect = false;

    do {
        redirect = false;
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        Log.d("Test","url: "+connection.getURL());

        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        connection.setInstanceFollowRedirects(false);

        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Cache-Control", "no-cache");
        connection.setRequestProperty("Content-Type","application/json;charset=utf-8");
        connection.setRequestProperty("Accept","application/json");

        OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
        writer.write("{\"test_value\":\"test\"}");
        writer.flush();
        writer.close();

        Log.d("Test","json sent");

        int httpResult = connection.getResponseCode();
        Log.d("Test","http response code: "+httpResult);
        if(httpResult == HttpURLConnection.HTTP_OK){
            Log.d("Test", IOUtils.toString(connection.getInputStream()));
            Log.d("Test", "result read");
        }
        else if(   httpResult == HttpURLConnection.HTTP_MOVED_PERM
                || httpResult == HttpURLConnection.HTTP_MOVED_TEMP
                || httpResult == HttpURLConnection.HTTP_SEE_OTHER){
            redirect = true;
            url = new URL(connection.getHeaderField("Location"));
        }
    } while (redirect);
} catch (MalformedURLException e) {
    Log.e("Test","exception while sending data to server",e);
} catch (ProtocolException e) {
    Log.e("Test","exception while sending data to server",e);
} catch (IOException e) {
    Log.e("Test","exception while sending data to server",e);
}