Android HttpURLConnection 在 post 请求中发送数据不起作用,但 javascript XMLHttpRequest 可以

Android HttpURLConnection sending data in post request doesnt work, but javascript XMLHttpRequest does

我有一个使用 mongodb、mongoose 和 node.js 的服务器。 我已经实现了一些 GET 和 POST 方法。

在 HTML 网站中,我可以 post 在 XMLHttpRequest 中向服务器发送数据,如下所示 javascript:

function postPlantType(base64){
    var httpPost = new XMLHttpRequest(),
        path = "http://...",               // real URL taken out here
        header = ('Content-Type','application/json'),
        data = JSON.stringify({image:base64});
    httpPost.onreadystatechange = function(err) {
        if (httpPost.readyState == 4 && httpPost.status == 201){
            console.log(httpPost.responseText);
        } else {
            console.log(err);
        }
    };

    path = "http://..."                   // real URL taken out here
    httpPost.open("POST", path, true);
    httpPost.send(data);
}

这很好用。现在我想创建一个 Android 应用程序,利用这样一个 POST 请求,但我的代码无法成功运行。这是我的代码:

    private class PostNewPlantTask extends AsyncTask<String, Integer, String> {
    String responseString = "";
    int response;
    InputStream is = null;

    protected String doInBackground(String... urls){
        DataOutputStream wr=null;
        try {
            URL url = new URL(urls[0]);  // urls[0] is the url of the http request "http://www..."
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000 /* milliseconds */);
            conn.setConnectTimeout(15000 /* milliseconds */);
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

            String json = "{\"image\":\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYE...\"}";

            Log.d("json", json.toString());

            conn.setRequestProperty("Content-length", json.getBytes().length + "");
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setAllowUserInteraction(false);

            OutputStream os = conn.getOutputStream();
            os.write( json.getBytes("UTF-8"));
            os.close();

            // Starts the query
            conn.connect();
            response = conn.getResponseCode();
            if (response >= 200 && response <=399){
                is = conn.getInputStream();
            } else {
                is = conn.getErrorStream();
            }

            // Convert the InputStream into a string
            String contentAsString = readIt(is, 200);
            responseString = contentAsString;
            conn.disconnect();
        } catch (Exception e) {
            responseString = "error occured: "+e;


        } finally {
            if (is != null){
                try { is.close();} catch (Exception e) {Log.d("HTTP POST planttypes","Exception occured at closing InputStream: "+e);}
            }
        }
        Log.d("HTTP POST plants", "The response is: " + response + responseString);
        return responseString;
    }

    protected void onPostExecute(String result){

        // TODO: nothing(?)
        // give user feedback(?)
    }

}

注意:如果我将 json 字符串更改为无效的 json 内容,例如删除最后一个“}”,服务器的响应是

400 "code":"InvalidContent","message":"Invalid JSON: Unexpected end of input"

所以我假设整个 json 字符串必须是正确的,如果它没有变化的话。

由于测试问题,我在这里对 base64 编码的图像字符串进行硬编码,而不是对真实图像进行编码。你可以在这个 jsfiddle 看到图片。 如果我没看错,它与我的 javascript 发出的请求完全相同,但我收到 500 内部服务器错误。 但是,为了获得更多信息,这里是为该请求调用的服务器函数 url:

function postNewPlantType(req, res, next){
    var json = JSON.parse(req.body);
    newPlantTypeData = {
        image:json.image
    };

    var imageBuffer = decodeBase64Image(json.image);

    newPlantType = new Planttype(newPlantTypeData);

    newPlantType.save(function(err){
        if (err) return next(new    restify.InvalidArgumentError(JSON.stringify(err.errors)));
        var fileName = cfg.imageFolder + "" + newPlantType._id + '.jpeg';
        fs.writeFile(fileName, imageBuffer.data, function(error){
            if (error) log.debug(error);
            log.debug("PlantType-ImageFile successfully created on server.");
        });
        res.send(201, newPlantType);
        log.debug("PlantType successfully saved in database.");
    });
}

我想知道的是,javascript 请求有效,但 android 请求无效。所以我假设我的 android 代码一定有错误。你能帮我解释一下,错误是什么,我必须改变什么吗?

您可能需要对其进行正确编码:

conn.connect();
DataOutputStream  printout = new DataOutputStream(conn.getOutputStream ());
printout.write(URLEncoder.encode(json.toString(),"UTF-8"));
printout.flush ();
printout.close ();
response = conn.getResponseCode();
...

经过很多天的调查,我终于通过更改线路得到了 201 响应

conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

嗯..我发送的是编码的 JSON 而不是 json 本身...