【问题标题】:Android Volley PUT requestAndroid Volley PUT 请求
【发布时间】:2014-11-02 07:45:04
【问题描述】:

总的来说,我是 Volley 和 Android 的新手。下面是我正在尝试执行的代码 sn-p(使用 Volley 的 Android),但它是服务器返回 400。使用另一个 REST 客户端效果很好。这是使用 PUT 方法向服务器发出的请求。

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    sendRequest();
}

private void sendRequest() {
    RequestQueue queue = Volley.newRequestQueue(this);

    final JSONObject jsonObject = new JSONObject();
    try {
        jsonObject.put("password", "ttttt");
        jsonObject.put("username", "tester3");
        jsonObject.put("token", "blah");
    } catch (JSONException e) {
        // handle exception
    }


    JsonObjectRequest putRequest = new JsonObjectRequest(Request.Method.PUT, url, jsonObject,
            new Response.Listener<JSONObject>()
            {
                @Override
                public void onResponse(JSONObject response) {
                    // response
                    Log.d("Response", response.toString());
                }
            },
            new Response.ErrorListener()
            {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // error
                    Log.d("Error.Response", error.toString());
                }
            }
    ) {

        @Override
        public Map<String, String> getHeaders()
        {
            Map<String, String> headers = new HashMap<String, String>();
            headers.put("Content-Type", "application/json");
            headers.put("Accept", "application/json");
            return headers;
        }

        @Override
        public byte[] getBody() {

            try {
                Log.i("json", jsonObject.toString());
                return jsonObject.toString().getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    queue.add(putRequest);
}

当我执行此代码时,我总是收到 400 Bad request,但我不知道为什么。 使用像 Postman 这样的另一个客户端,它可以按预期工作。这是邮递员的要求:

原始请求:
{ “令牌”:“废话”, “密码”:“tttt”, “用户名”:“tester3” }

Headers: Content-Type: application/json

我看不出请求有什么问题,希望有人能指出我做错了什么?

【问题讨论】:

  • 你找到解决方案了吗?我也陷入了同样的境地。
  • 恐怕我没有,没时间了,继续使用改造。
  • 即使我没时间了。结帐改造,但无法在短时间内掌握。但是您的问题有助于解决问题。在标题中添加headers.put("Accept", "application/json" 解决了它。谢谢。
  • 很高兴它让你受益:)

标签: java android rest android-volley


【解决方案1】:

有时,在 getHeaders() 中添加标头“Content-Type”、“application/json”并不能更好地覆盖 getBodyContentType() 并在此处返回标头。

所以和,

public Map<String, String> getHeaders()
    {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/json"); 
        return headers;
    }

还要加,

    @Override
    public String getBodyContentType() {
        return "application/json";
    }

这在使用 POST 时对我有用。

【讨论】:

    【解决方案2】:

    JsonObjectRequest 默认添加Content-Type: application/json; charset=utf-8。您的 headers.put("Content-Type", "application/json"); 添加了另一个 Content-Type 并且某些应用程序无法使用多个 Content-Type 定义。您应该尝试删除headers.put("Content-Type", "application/json");

    【讨论】:

    • 它解决了我的问题。有时你只是忘记了这些基本的东西。
    【解决方案3】:

    我一直在寻找带有 Kotlin 语言请求正文但所有答案都是 Java 的 Android Volley Put (JSON)。也许有人在 Kotlin 中寻找答案,所以我用 Kotlin 语言创建了带有请求正文的 Put:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        // let's say we have token, apiLink, val1, val2, val3 as a String
        // created a function sendPutRequest()
        sendPutRequest(token, apiLink, val1, val2, val3)
    }
    
    private fun sendPutRequest(
        token: String,
        apiLink: String,
        val1: String,
        val2: String,
        val3: String
    ) {
    
        val queue = Volley.newRequestQueue(this)
        val jsonObject = JSONObject()
    
        try {
            jsonObject.put("token", token)
            jsonObject.put("val1", val1)
            jsonObject.put("val2", val2)
            jsonObject.put("val3", val3)
        } catch (e: JSONException) {
            // handle exception
            Log.i("json_error: ", "$e")
        }
    
         val putRequest: JsonObjectRequest =
            object : JsonObjectRequest(
                Method.PUT, apiLink, jsonObject,
                Response.Listener { response ->
                    // response
                    Log.i("response: ", "$response")
                },
                Response.ErrorListener { error ->
                    // error
                    Log.i("error: ", "$error")
                }
            ) {
    
                override fun getHeaders(): Map<String, String> {
                    val headers: MutableMap<String, String> =
                        HashMap()
                    headers["Content-Type"] = "application/json"
                    headers["Accept"] = "application/json"
                    return headers
                }
    
                override fun getBody(): ByteArray {
                        Log.i("json", jsonObject.toString())
                        return jsonObject.toString().toByteArray(charset("UTF-8"))
                }
    
            }
        queue.add(putRequest)
    }
    
    

    【讨论】:

      【解决方案4】:

      尝试使用 StringRequest,如下所示:

      StringRequest putRequest = new StringRequest(Request.Method.PUT, url,
              new Response.Listener<String>()
              {
      @Override
      public void onResponse(String response) {
              // response
              Log.d("Response", response.toString());
              }
              },
              new Response.ErrorListener()
              {
      @Override
      public void onErrorResponse(VolleyError error) {
              // error
              Log.d("Error.Response", error.toString());
              }
              }
              ) {
      
      @Override
      public Map<String, String> getHeaders()
              {
              Map<String, String> headers = new HashMap<String, String>();
              headers.put("Content-Type", "application/json");
              //or try with this:
              //headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
              return headers;
              }
      @Override
      protected Map<String, String> getParams() {
              Map<String, String> params = new HashMap<String, String>();
              params.put("password", "ttttt");
              params.put("username", "tester3");
              params.put("token", "blah");
              return params;
              }
              };
      
              queue.add(putRequest);
              }
      

      【讨论】:

        【解决方案5】:
         @Override
        public String getBodyContentType() {
            return "application/json";
        }
        

        这对我使用 PUT 请求很有用。

        【讨论】:

          【解决方案6】:

          某些托管服务提供商会阻止某些请求方法,例如 PUT 或 DELETE - 例如000webhost blocks PUT and DELETE requests for free users。如果 PUT 方法由于某种原因在主机上被阻止,您可以将其替换为 POST 方法。我知道,这不是最好的解决方案,但它确实有效。

          【讨论】:

            【解决方案7】:

            我花了很多时间寻找如何做到这一点。对我有用的是改变

            Request.Method.PUT
            

            Request.Method.POST
            

            【讨论】:

            • 但这是关于 PUT 的问题
            • 你是个天才