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

Android Getting=java.net.ProtocolException:写入OutpuStream时超出了0字节的内容长度限制,java,android,json,Java,Android,Json,我正在尝试使用HttpURLConnection进行post调用&通过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.x

我正在尝试使用HttpURLConnection进行post调用&通过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;
    }
}
我得到一个例外:

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库

httpURLConnection.setRequestProperty("Content-length", "0");
去掉这个。在这个类中,您根本不需要设置内容长度,如果要发送消息正文,当然也不需要设置为零

httpURLConnection.setRequestMethod("POST");
替换为

httpURLConnection.setDoOutput(true);
否则不允许进行任何输出

编辑对于怀疑者,以下代码未设置内容长度,但在发送
内容长度后“正确”返回405响应代码:9\r\n
头,由
HttpURLConnection
(以及
POST
的请求类型和
内容类型:application/x-www-form-urlencoded\r\n
头,两者均不由此代码设置):

删除此项。使用此类根本不需要设置内容长度,如果要发送消息正文,当然也不需要设置为零

httpURLConnection.setRequestMethod("POST");
替换为

httpURLConnection.setDoOutput(true);
否则不允许进行任何输出

编辑对于怀疑者,以下代码未设置内容长度,但在发送
内容长度后“正确”返回405响应代码:9\r\n
头,由
HttpURLConnection
(以及
POST
的请求类型和
内容类型:application/x-www-form-urlencoded\r\n
头,两者均不由此代码设置):


我不知道POST+输出是可行的。但是错误特别提到了内容长度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);

我不知道POST+输出是可行的。但是错误特别提到了内容长度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);

我不明白你的第一句话。否则你会怎么写一篇文章?你不应该设置内容长度。Java会为你做的。@我在用改型http API写文章和JSON,没有任何问题。我怎么写JSON到HttpURLConnection?代码似乎很简单。Thanks@StephenC事实上确实如此,这正是它是如何做到的。这也是为什么在调用接收的方法之前不会发送任何内容。除非您使用分块或固定长度模式。您的最后一句话与您的断言不一致。不,不是。请查看通过网络发送的内容。请求中根本没有内容长度头。因此,没有设置任何内容长度头对你来说。@StephenC我离能做到这一点还有60万公里,但我已经见过很多次了。如果不能做到这一点,HTTP连接池和keepalive将是不可能的,除非每个人都使用分块或固定长度传输模式。我20年来从未设置过内容长度头。这里有很多公认的答案都是这样说的。我不知道I don’我不明白你的第一句话。否则你会怎么写一篇文章?你不应该设置内容长度。Java会为你做的。@我正在使用改进的http API做文章和JSON,没有任何问题。我该如何向HttpURLConnection写JSON?代码似乎很简单。Thanks@StephenC事实上是这样的,我就是这样想的这也是为什么在调用接收方法之前不会发送任何内容。除非您使用的是分块或固定长度模式。您的最后一句话与您的断言不一致。不,不是。请查看通过网络发送的内容。请求中根本没有内容长度头。因此,没有任何内容长度头设置为y你。@StephenC我离能做到这一点还有60万公里,但我已经见过很多次了。如果不能做到这一点,HTTP连接池和keepalive将是不可能的,除非每个人都使用分块或固定长度传输模式。我20年来从未设置过内容长度头。这里有很多公认的答案都这么说。我尝试了remo正在使用httpURLConnection.setRequestMethod(“POST”)&仅使用httpURLConnection.setDoOutput(true)),我也尝试保留这两个,但仍然是相同的错误。是否删除了无效的
内容长度设置?是否阅读了此答案?我尝试删除httpURLConnection.setRequestMethod(“POST”)&仅使用httpURLConnection.setDoOutput(正确);,我也尝试保留这两个选项,但仍然是相同的错误。您是否删除了无效的
内容长度设置?您是否阅读了此答案?