Android Getting = java.net.ProtocolException:写入OutpuStream时超出了0字节的内容长度限制

时间:2017-10-13 23:44:02

标签: java android json

我正在尝试使用HttpURLConnection&通过HttpURLConnection的OutputStream发送JSON数据:

请参阅下面的课程:

package com.app.data.pojos;

import android.os.AsyncTask;
import android.util.Log;
import com.app.xyz.data.GDParser;
import com.app.xyz.model.GDUser;
import com.app.xyz.model.GDUserStatus;
import com.app.xyz.utils.APrefs;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by arynaim on 10/12/17.
 */

public class PostUserStatus extends AsyncTask<String, Void, GDUserStatusResponse> {

    private static final String TAG = "PostUserStatus";
    private GDUser gdUser;

    public PostUserStatus(GDUser gdUser) {
        this.gdUser = gdUser;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

    }

    @Override
    protected GDUserStatusResponse doInBackground(String... urls) {

        Log.i(TAG,"doInBackground(), gDUserStatusResponse url:"+urls[0]);
        HttpURLConnection httpURLConnection = null;
        GDUserStatus gdUserStatus = null;
        JsonElement jsonElemnt = null;
        JsonObject jsonObject = null;
        GDUserStatusResponse gDUserStatusResponse = null;
        try {
            URL url = new URL(urls[0]);
            httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Content-length", "0");
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setAllowUserInteraction(false);
            httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            httpURLConnection.setRequestProperty("Authorization", new APrefs().getNMToken());
            //httpURLConnection.connect();
            JSONObject userIdJsonObject = new JSONObject();
            userIdJsonObject.put("userID",getGdUser().getUserId());
            //post json via OutputStream
            OutputStream os = httpURLConnection.getOutputStream();
            os.write(userIdJsonObject.toString().getBytes());
            os.flush();
            Log.i(TAG,"doInBackground(), http request"+url.toString());


            int status = httpURLConnection.getResponseCode();

            switch (status) {
                case 200:
                    Log.i(TAG,"doInBackground(), http response status:"+status);
                    BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
                    StringBuilder sb = new StringBuilder();
                    String line;
                    while ((line = br.readLine()) != null) {
                        sb.append(line + "\n");
                    }

                    jsonElemnt = new JsonParser().parse(sb.toString());
                    jsonObject = jsonElemnt.getAsJsonObject();
                    gdUserStatus = new GDParser().parseStatusResponse(jsonObject);
                    gDUserStatusResponse = new GDUserStatusResponse();
                    gDUserStatusResponse.setGdUserStatus(gdUserStatus);
                    br.close();
                    break;
                default:
                    Log.e(TAG,"doInBackground(), http response error status:"+status);
                    //TODO: handle error responses
                    //TODO: if stale token refresh & try again
                    break;

            }



        } catch (IOException ex) {

            ex.printStackTrace();

        } catch (Exception ex) {

            ex.printStackTrace();

        } finally {
            if (httpURLConnection != null) {
                try {
                    httpURLConnection.disconnect();
                } catch (Exception ex) {
                ex.printStackTrace();
                }
            }
        }

        return gDUserStatusResponse;
    }//end doInBackgroud

    protected void onPostExecute(GDUserStatusResponse gDUserStatusResponse) {

        Log.i(TAG,"onPostExecute(), gDUserStatusResponse:"+gDUserStatusResponse);

    }

    public GDUser getGdUser() {
        return gdUser;
    }

    public void setGdUser(GDUser gdUser) {
        this.gdUser = gdUser;
    }
}

但是当我写信给

os.write(userIdJsonObject.toString().getBytes());

我遇到了这个例外:

10-13 16:30:46.737 15395-17467/com.app.xyz I/PostUserStatus: doInBackground(), gDUserStatusResponse url:https://development.xyz.com/api/v1/users/status
10-13 16:30:46.741 15395-17467/com.app.xyz I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
10-13 16:30:46.741 15395-17467/com.app.xyz I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err: java.net.ProtocolException: exceeded content-length limit of 0 bytes
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at com.android.okhttp.internal.http.RetryableSink.write(RetryableSink.java:58)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at com.android.okhttp.okio.RealBufferedSink.flush(RealBufferedSink.java:221)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at com.android.okhttp.okio.RealBufferedSink$1.flush(RealBufferedSink.java:204)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at com.app.xyz.data.pojos.PostUserStatus.doInBackground(PostUserStatus.java:63)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at com.app.xyz.data.pojos.PostUserStatus.doInBackground(PostUserStatus.java:24)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:304)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
10-13 16:30:46.833 15395-17467/com.app.xyz W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
10-13 16:30:46.834 15395-17467/com.app.xyz W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
10-13 16:30:46.834 15395-17467/com.app.xyz W/System.err:     at java.lang.Thread.run(Thread.java:762)
10-13 16:30:46.835 15395-15395/com.app.xyz I/PostUserStatus: onPostExecute(), gDUserStatusResponse:null

我不想使用除Android / Java提供的基础之外的任何Http库。

2 个答案:

答案 0 :(得分:1)

httpURLConnection.setRequestProperty("Content-length", "0");

删除它。您不需要使用此类设置内容长度,如果您打算发送邮件正文,则肯定不会为零。

httpURLConnection.setRequestMethod("POST");

将其替换为

httpURLConnection.setDoOutput(true);

否则你不允许做任何输出。

编辑对于怀疑论者,以下代码未设置内容长度,但在线路上发送Content-length: 9\r\n标头后,“正确”返回405响应代码自动由HttpURLConnection(以及POSTContent-Type: application/x-www-form-urlencoded\r\n标头的请求类型(均未由此代码设置):

    URL url = new URL("http://google.com");
    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
    conn.setDoOutput(true);
    OutputStream    out = conn.getOutputStream();
    out.write("xxxx=yyyy".getBytes());
    out.flush();
    int responseCode = conn.getResponseCode();
    System.out.println("responseCode="+responseCode);
    InputStream in = (responseCode == 200) ? conn.getInputStream() : conn.getErrorStream();
    int c;
    while ((c = in.read()) != -1)
    {
        System.out.write(c);
    }
    in.close();
    conn.disconnect();

答案 1 :(得分:-1)

我不知道POST +输出是可行的。但该错误特别提到了Content-Length 0。

    JSONObject userIdJsonObject = new JSONObject();
    userIdJsonObject.put("userID",getGdUser().getUserId());
    byte[] content = userIdJsonObject.toString().getBytes();

    httpURLConnection.setDoOutput(true);
    httpURLConnection.setRequestProperty("Content-length",
            String.valueOf(content.length));
    ...
    OutputStream os = httpURLConnection.getOutputStream();
    os.write(content);