在安卓设备上使用HttpURLConnection进行PHP HTTP POST请求

6
问题:
所遇问题是它无法发布到由GoDaddy托管的在线数据库。那么我的问题是为什么它不能发布,我该如何修复它才能发布?
问题描述: PHP页面没有接收到传递给它的名称值对。
编辑: 按照建议修改了代码以使用HttpURLConnection... 我已经缩小了问题范围,发现它没有检索到fbid。
正如您可以看出来的那样,我在这里做了很多功课... 这是我的日志记录,显示在postthread类中设置的内容。这是执行发布的类:
07-02 16:41:45.108: I/PROJECTCARUSO(12308): response: {"posts":[null]}

HttpPostThread:

public class HttpPostThread extends Thread {
    public static final int FAILURE = 0;
    public static final int SUCCESS = 1;


    private URL url;
    ArrayList<NameValuePair> pairs;

    public HttpPostThread(URL sERVICE_URL, ArrayList<NameValuePair> pairs, final Handler handler)
    {
        Log.i("PROJECTCARUSO", "Posting to URL: " + sERVICE_URL);
        this.url =sERVICE_URL;
        this.pairs = pairs;
        if(pairs==null){
            Log.i("PROJECTCARUSO", "URL parms were null");
            this.pairs = new ArrayList<NameValuePair>();
        }
    }

    @Override
    public void run()
    {
        try {
            HttpURLConnection conn;
            String param="";

            for (NameValuePair nvp : pairs) {
                //you need to encode ONLY the values of the parameters
                if (param == "") {
                    param=nvp.getName() + "=" + URLEncoder.encode(nvp.getValue(),"UTF-8");
                } else {
                    param+= "&" + nvp.getName() + "=" + URLEncoder.encode(nvp.getValue(),"UTF-8");
                }
            }

            Log.i("PROJECTCARUSO", "param: " + param.toString());
            // Create connection
            conn=(HttpURLConnection)url.openConnection();
            //set the output to true, indicating you are outputting(uploading) POST data
            conn.setDoOutput(true);
            //once you set the output to true, you don't really need to set the request method to post, but I'm doing it anyway
            conn.setRequestMethod("POST");

            //Android documentation suggested that you set the length of the data you are sending to the server, BUT
            // do NOT specify this length in the header by using conn.setRequestProperty("Content-Length", length);
            //use this instead.
            conn.setFixedLengthStreamingMode(param.getBytes().length);
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            //send the POST out
            PrintWriter out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.close();

            //build the string to store the response text from the server
            String response= "";

            //start listening to the stream
            Scanner inStream = new Scanner(conn.getInputStream());

            //process the stream and store it in StringBuilder
            while(inStream.hasNextLine())
            response+=(inStream.nextLine());

            Log.i("PROJECTCARUSO","response: " + response);
        }
        //catch some error
        catch(MalformedURLException ex){  
            Log.i("PROJECTCARUSO", ex.toString());

        }
        // and some more
        catch(IOException ex){

            Log.i("PROJECTCARUSO", ex.toString());

        }

    }

    public static boolean isNumeric(String str)  
    {  
      try  
      {  
        double d = Double.parseDouble(str);  
      }  
      catch(NumberFormatException nfe)  
      {  
        return false;  
      }  
      return true;  
    }
}

以下是 PHP 代码:

        <?php 

//Make connection
$con = mysqli_connect('...','...','...') ;


//check connection
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

//change db to andriodnfp db
mysqli_select_db($con, 'andriodnfp');

$table= 'USER';
$id=0;

$fbid = htmlspecialchars($_GET["fbid"]);
$social = htmlspecialchars($_GET["social"]);


$name = htmlspecialchars($_GET["name"]);
$name = !empty($name) ? "'$name'" : "NULL";

$fname = htmlspecialchars($_GET["fname"]);
$fname = !empty($fname) ? "'$fname'" : "NULL";

$username = htmlspecialchars($_GET["username"]);
$username = !empty($username) ? "'$username'" : "NULL";

$email = htmlspecialchars($_GET["email"]);
$email = !empty($email) ? "'$email'" : "NULL";

$picture = htmlspecialchars($_GET["picture"]);
$picture = !empty($picture) ? "'$picture'" : "NULL";

$other = htmlspecialchars($_GET["other"]);
$other = !empty($other) ? "'$other'" : "NULL";

if (!$fbid == '') {

    if (!mysqli_query($con, 'INSERT INTO '.$table.' ( facebookID, social_outlet, Name, first_name, username, email, picture, significant_other) VALUES ("'.$fbid.'","'.$social.'","'.$name.'","'.$fname.'","'.$username.'","'.$email.'","'.$picture.'","'.$other.'")')) {
        printf("Errormessage: %s\n", mysqli_error($con));
        die();
    } else {
        $posts = array('auto_increment_id'=>mysqli_insert_id($con));
    };
} else {
    printf("Errormessage: %s\n", "Facebook ID was null");
    printf("Errormessage: %s\n", $fbid );
    printf("Errormessage: %s\n", $social);
    printf("Errormessage: %s\n", $name);
    printf("Errormessage: %s\n", $fname);
    printf("Errormessage: %s\n", $username);
    printf("Errormessage: %s\n", $email);
    printf("Errormessage: %s\n", $picture);
    printf("Errormessage: %s\n", $other);
    die();
}

mysqli_close($con);

//$posts = array($json);
$posts = array($posts);
header('Content-type: application/json');
echo json_encode(array('posts'=>$posts));

?>

Apache日志:

166.147.72.174 - - [19/Jun/2013:16:47:41 -0700] "POST ...post.php? HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 195224
166.147.72.174 - - [19/Jun/2013:16:49:08 -0700] "POST ...post.php? HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 13848
166.147.72.174 - - [19/Jun/2013:16:50:57 -0700] "POST ...post.php? HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 17899
166.147.72.174 - - [19/Jun/2013:16:52:14 -0700] "POST ...post.php HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 12514
166.147.72.174 - - [19/Jun/2013:16:53:35 -0700] "POST ...post.php HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 15190
166.147.72.174 - - [19/Jun/2013:16:54:56 -0700] "POST ...post.php HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 14373
166.147.72.174 - - [19/Jun/2013:16:56:50 -0700] "POST ...post.php HTTP/1.1" 200 155 "-" "Apache-HttpClient/UNAVAILABLE (java 1.4)" 0 "x-httpd-php5-3" "/var/chroot/home/content/31/9124131/html/android/com.projectcaruso/naturalfamilyplaning/post.php" 12017

编辑:

我甚至尝试了以下的Java代码:

public void run() {
    try {
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setReadTimeout(10000);
    conn.setConnectTimeout(15000);

        conn.setRequestMethod("POST");

    conn.setDoInput(true);
    conn.setDoOutput(true);

    List<NameValuePair> params = new ArrayList<NameValuePair>();
    for (NameValuePair nvp : pairs) {
    //you need to encode ONLY the values of the parameters
        params.add(new BasicNameValuePair(nvp.getName(), nvp.getValue()));
        Log.i("PROJECTCARUSO", "NVP: " + nvp.getName() + " - " + nvp.getValue());
    }


    OutputStream os = conn.getOutputStream();
    BufferedWriter writer = new BufferedWriter(
            new OutputStreamWriter(os, "UTF-8"));
    writer.write(getQuery(params));
    writer.close();
    os.close();

    conn.connect();

    //build the string to store the response text from the server
    String response= "";

    //start listening to the stream
    Scanner inStream = new Scanner(conn.getInputStream());

    //process the stream and store it in StringBuilder
    while(inStream.hasNextLine())
    response+=(inStream.nextLine());

    Log.i("PROJECTCARUSO","response: " + response);

    } catch (ProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

     catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }

1
@Jonast92,你的评论并不具有建设性。但是,如果你有任何建议,尽管与主题无关,我很乐意听取。 - jcaruso
@jcaruso VALUES ("'.$fbid.'","'.$social.'", 等等,意味着我可以在您的系统中插入各种奇怪的代码。如果我想的话,我甚至可以删除您的数据库。您必须使用预处理语句,在这种情况下,您创建一个接受常量的模板,这些常量不能影响您的数据库。您不需要单引号,只是没有使用准备好的语句。我在以前的答案中已经多次提到过这一点。您也可以通过谷歌搜索来了解。 - Jonast92
@Jonast92,感谢您的“建设性”评论,我知道什么是SQL注入,但目前我只关心它能否正常工作,一旦它正常工作了,我会更加关注安全性。 - jcaruso
你应该使用 http://developer.android.com/reference/java/net/HttpURLConnection.html 类。 - Sunny
我尝试将它转换为HttpURLConnection,但没有任何改变...请看代码。 - jcaruso
显示剩余5条评论
2个回答

1

你必须在所有地方使用$_POST而不是$_GET


1
那是我能给出的最长的答案 :) - OcuS

1

假设您使用Apache HttpClient作为默认客户端。

您需要更多关于WIRE和HEADER的数据。 Apache logger docs 显示了如何启用这些日志记录器。请阅读有关日志记录的Apache文档。

以下是您将看到的示例(您将精确知道客户端和服务器之间正在发生什么)。

完整记录在Apache HttpClient中:

D/ch.boye.httpclientandroidlib.wire( 1175): >> "PUT /1/classes/Books/8NUX0YP5XK HTTP/1.1[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "Content-Length: 375[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "Content-Type: text/plain; charset=ISO-8859-1[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "Host: api.parse.com[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "Connection: Keep-Alive[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "X-Parse-Application-Id: 3[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "X-Parse-REST-API-Key: kVl9[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): >> "[\r][\n]"
D/ch.boye.httpclientandroidlib.headers( 1175): >> PUT /1/classes/Books/8NUX0YP5XK HTTP/1.1
D/ch.boye.httpclientandroidlib.headers( 1175): >> Content-Length: 375
D/ch.boye.httpclientandroidlib.headers( 1175): >> Content-Type: text/plain; charset=ISO-8859-1
D/ch.boye.httpclientandroidlib.headers( 1175): >> Host: api.parse.com
D/ch.boye.httpclientandroidlib.headers( 1175): >> Connection: Keep-Alive
D/ch.boye.httpclientandroidlib.headers( 1175): >> X-Parse-Application-Id: 3K
D/ch.boye.httpclientandroidlib.headers( 1175): >> X-Parse-REST-API-Key: kVl5Z
D/ch.boye.httpclientandroidlib.wire( 1175): >> "{"pages":{"__op":"Add","objects":[{"__type":"Pointer","ClassName":"TestVoiceObject","objectId":"bsKyc8mKV7"},{"__type":"Pointer","ClassName":"TestVoiceObject","objectId":"hehlqEUJw8"},{"__type":"Pointer","ClassName":"TestVoiceObject","objectId":"rtbhCb37tq"},{"__type":"Pointer","ClassName":"TestVoiceObject","objectId":"84zjWpJy6y"}]},"ACL":{"*":{"read":true,"write":true}}}"
D/ch.boye.httpclientandroidlib.wire( 1175): << "HTTP/1.1 200 OK[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Access-Control-Allow-Origin: *[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Access-Control-Request-Method: *[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Cache-Control: max-age=0, private, must-revalidate[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Content-Type: application/json; charset=utf-8[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Date: Mon, 08 Apr 2013 19:51:59 GMT[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "ETag: "172e8ee0c4828b5fce3303c078b8f2ad"[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Server: nginx/1.2.2[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Set-Cookie: _parse_session=BAh7BkkiD3d989bfe; domain=.parse.com; path=/; expires=Sat, 08-Apr-2023 19:51:59 GMT; secure; HttpOnly[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Status: 200 OK[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "X-Runtime: 0.041462[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "X-UA-Compatible: IE=Edge,chrome=1[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Content-Length: 500[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "Connection: keep-alive[\r][\n]"
D/ch.boye.httpclientandroidlib.wire( 1175): << "[\r][\n]"
D/class ch.boye.httpclientandroidlib.impl.conn.DefaultClientConnection( 1175): Receiving response: HTTP/1.1 200 OK
D/ch.boye.httpclientandroidlib.headers( 1175): << HTTP/1.1 200 OK
D/ch.boye.httpclientandroidlib.headers( 1175): << Access-Control-Allow-Origin: *
D/ch.boye.httpclientandroidlib.headers( 1175): << Access-Control-Request-Method: *
D/ch.boye.httpclientandroidlib.headers( 1175): << Cache-Control: max-age=0, private, must-revalidate
D/ch.boye.httpclientandroidlib.headers( 1175): << Content-Type: application/json; charset=utf-8
D/ch.boye.httpclientandroidlib.headers( 1175): << Date: Mon, 08 Apr 2013 19:51:59 GMT
D/ch.boye.httpclientandroidlib.headers( 1175): << ETag: "172e8ee0c4828b5fce3303c078b8f2ad"
D/ch.boye.httpclientandroidlib.headers( 1175): << Server: nginx/1.2.2
D/ch.boye.httpclientandroidlib.headers( 1175): << Set-Cookie:

说得太早了...Godaddy那边有Apache日志...让我看看这个,看上面的编辑。 - jcaruso
我看到了这个解释:http://stackoverflow.com/questions/3938477/servlet-unavailable-in-appengine-with-android-client。 - jcaruso
我的错误。看起来不像是服务器端的问题。 - Robert Rowntree
使用Curl从CLI测试您的PHP。在开始使用Android客户端之前,您应该确保您的服务器在响应正文中发布良好的JSON。 - Robert Rowntree
使用curl的cli?请解释一下。 - jcaruso
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接