使用HttpUrlConnection获取“已连接”的Android POST请求

时间:2017-02-05 12:07:58

标签: android post httpurlconnection

我正在尝试使用HttpUrlConnection进行POST调用,但没有成功。 我经常收到'IllegalStateException:已连接'错误消息。 我对重用连接不感兴趣。请检查我的代码并告诉我我是否做错了什么:

public static final int CONNECTION_TIME_OUT = 10000;

public SimpleResponse callPost(String urlTo, Map<String, String> params) {
    System.setProperty("http.keepAlive", "false");
    HttpURLConnection conn = null;
    SimpleResponse response = new SimpleResponse(0, null);
    try {
        URL url = new URL(urlTo);
        conn = (HttpURLConnection) url.openConnection();
        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);
        conn.setConnectTimeout(CONNECTION_TIME_OUT);
        conn.setReadTimeout(CONNECTION_TIME_OUT);
        conn.setInstanceFollowRedirects(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Connection", "close");
        conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
        conn.setDoOutput(true);

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

        int responseCode = conn.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            InputStream in = conn.getInputStream();
            String result = StringUtils.fromInputStream(in);
            response = new SimpleResponse(responseCode, result);
            in.close();
        } else {
            response = new SimpleResponse(responseCode, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (conn != null) {
        conn.disconnect();
    }
    return response;
}

private String paramsToString(Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }
        Uri.Builder builder = new Uri.Builder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            builder.appendQueryParameter(entry.getKey(), entry.getValue());
        }
        return builder.build().getEncodedQuery();
    }

更新

有时工作,有时不工作! 在一些项目上工作,在其他项目上没有! 完全相同的代码,每次都有相同的例外:已经连接了 为什么我每次都无法获得新的连接?

3 个答案:

答案 0 :(得分:3)

我认为你的问题是:

        conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));

我无法看到postDataBytes的声明位置,但由于您正在处理paramsToString中的参数,我猜他们没有任何关系。

现在,我不是RFC 2616(HTTP)的专家,但我认为正在发生的是postDataBytes的长度大于您的请求大小,因此服务器没有断开套接字它的结束。这些URLConnection对象是合并的,所以当你去获取一个连接对象时,它的值已被清理以便重用,但实际的连接仍然是打开的。

这是我认为你应该尝试的一些代码。如果它不能解决您的问题,我不会得到代表奖金,但它仍然比您拥有的更正确:

private static final String CHARSET = "ISO-8859-1";  // or try "UTF-8"

public SimpleResponse callPost(String urlTo, Map<String, String> params) {

// get rid of this...
//    System.setProperty("http.keepAlive", "false");

    HttpURLConnection conn = null;
    SimpleResponse response = new SimpleResponse(0, null);
    try {
        URL url = new URL(urlTo);
        conn = (HttpURLConnection) url.openConnection();
        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);
        conn.setConnectTimeout(CONNECTION_TIME_OUT);
        conn.setReadTimeout(CONNECTION_TIME_OUT);
        conn.setInstanceFollowRedirects(false);
        conn.setRequestMethod("POST");
// ... and get rid of this
//        conn.setRequestProperty("Connection", "close");
        conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=" + CHARSET);

        String content = paramsToString(params);
        int length = content.getBytes(Charset.forName(CHARSET)).length;
        conn.setRequestProperty("Content-Length", Integer.toString(length));
        conn.setDoOutput(true);

        OutputStream os = conn.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, CHARSET));
        writer.write(content);
        writer.flush();
        writer.close();
        os.close();

        int responseCode = conn.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            InputStream in = conn.getInputStream();
            String result = StringUtils.fromInputStream(in);
            response = new SimpleResponse(responseCode, result);
            in.close();
        } else {
            response = new SimpleResponse(responseCode, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (conn != null) {
        conn.disconnect();
    }
    return response;
}

我为任何编译错误道歉。没有IDE,我没用。我尽力证明了这一点。

我使用了Latin-1编码。如果这不适合你,你可以试试UTF-8。

您可以尝试的另一件事是完全放弃内容长度并致电

        conn.setChunkedStreamingMode(0);

是的,我意识到getBytes()电话和OutputStreamWriter正在重复相同的过程。一旦解决了这个问题,你就可以继续工作。

答案 1 :(得分:1)

我似乎无法弄清楚为什么会出现“已经连接的错误”,但这是我用来发出POST请求的代码。我在发送请求后关闭输入/输出流和连接,这可能会对你有帮助(虽然我不确定)

try {
        URL url = new URL(stringURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
        connection.setRequestProperty("Accept","application/json");
        //connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
        //connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setReadTimeout(10*1000);
        connection.setUseCaches(false);
        connection.setDoInput(true);
        connection.setDoOutput(true);

        //Request
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.writeBytes(params[1]);
        wr.flush();
        wr.close();

        //Response
        InputStream is = connection.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        String line;
        response = new StringBuffer();
        //Expecting answer of type JSON single line {"json_items":[{"status":"OK","message":"<Message>"}]}
        while ((line = rd.readLine()) != null) {
            response.append(line);
        }
        rd.close();
        System.out.println(response.toString()+"\n");
        connection.disconnect(); // close the connection after usage

    } catch (Exception e){
        System.out.println(this.getClass().getSimpleName() + " ERROR - Request failed");
    }

答案 2 :(得分:0)

网上有一些可能对你有所帮助

  1. Android Httpurlconnection发布和获取请求教程here

  2. 如何将HttpURLConnection POST数据用于Web服务器? here

  3. 使用HttpURLConnection教程进行Android POST和GET请求here