【问题标题】:Sending HTTP DELETE request in Android在 Android 中发送 HTTP DELETE 请求
【发布时间】:2012-04-26 17:44:14
【问题描述】:

我的客户端的 API 指定要删除一个对象,必须发送一个 DELETE 请求,其中包含描述内容的 Json 标头数据。实际上,它与添加对象的调用相同,这是通过 POST 完成的。这工作正常,我的代码的胆量如下:

HttpURLConnection con = (HttpURLConnection)myurl.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setUseCaches(false);
con.connect();
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(data); // data is the post data to send
wr.flush();

为了发送删除请求,我将请求方法相应地更改为“DELETE”。但是我收到以下错误:

java.net.ProtocolException: DELETE does not support writing

那么,我的问题是,如何从 Android 发送包含标头数据的 DELETE 请求?我错过了这一点 - 您是否能够将标头数据添加到 DELETE 请求中?谢谢。

【问题讨论】:

    标签: android httpwebrequest


    【解决方案1】:

    有问题的行是con.setDoOutput(true);。删除它将修复错误。

    您可以使用addRequestPropertysetRequestProperty 将请求标头添加到DELETE,但您不能添加请求正文。

    【讨论】:

    • As often seen here on SO, the only correct answer is not elected and has no upvotes :(
    • 如果我需要发送一些带 DELETE 的 json 怎么办?
    • @konopko 或将其作为 URL 的一部分或作为标题发送
    【解决方案2】:

    这是 HttpURLConnection 在旧 Android 版本 (

    虽然您可以选择使用HttpClient,但我不推荐它,因为它是一个旧库,有几个问题是removed from Android 6

    我会推荐使用一个新的最近的库,比如OkHttp

    OkHttpClient client = new OkHttpClient();
    Request.Builder builder = new Request.Builder()
        .url(getYourURL())
        .delete(RequestBody.create(
            MediaType.parse("application/json; charset=utf-8"), getYourJSONBody()));
    
    Request request = builder.build();
    
    try {
        Response response = client.newCall(request).execute();
        String string = response.body().string();
        // TODO use your response
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    【讨论】:

      【解决方案3】:

      getOutputStream() 仅适用于具有正文的请求,例如 POST。在没有正文的请求上使用它,比如 DELETE,会抛出一个 ProtocolException。相反,您应该使用 addHeader() 添加标题,而不是调用 getOutputStream()。

      【讨论】:

      • 我在 java.net.HttpURLConnection 中没有看到 addHeader() 方法 - 你指的是什么方法?
      【解决方案4】:

      我知道有点晚了,但如果有人像我一样在谷歌上搜索,我会这样解决:

          conn.setRequestProperty("X-HTTP-Method-Override", "DELETE");
          conn.setRequestMethod("POST");
      

      【讨论】:

      • 谢谢!这个问题让我抓狂,但你的解决方案有帮助
      • 这仅在您的服务器配置为使用该自定义标头时才有效。这很常见,但不是标准的。一些服务器端 API 框架会看到标头并说,“哦,好吧,这实际上是一个删除方法,但他们使用的是 POST”。你可以自己编程这个行为。
      【解决方案5】:

      DELETE 请求是 GET 请求的扩展形式,根据 android 文档,您不能在 DELETE 请求的正文中编写。 HttpUrlConnection 将抛出“无法写入协议异常”。

      如果你还想在body中写参数,建议你使用OKHttp库。

      OKHttp documentation

      如果您有兴趣使用更简单的库,那么您可以尝试 SimpleHttpAndroid library

      这里要记住的一件事是,如果您没有在正文中写任何内容,则删除该行

      conn.setDoOutput(true);
      

      谢谢,希望对你有帮助。

      【讨论】:

        【解决方案6】:

        试试下面的方法调用 HttpDelete 方法,它对我有用,希望对你也有用

        String callHttpDelete(String url){
        
                     try {
                            HttpParams httpParams = new BasicHttpParams();
                            HttpConnectionParams.setConnectionTimeout(httpParams, 15000);
                            HttpConnectionParams.setSoTimeout(httpParams, 15000);
        
                            //HttpClient httpClient = getNewHttpClient();
                            HttpClient httpClient = new DefaultHttpClient();// httpParams);
        
        
                            HttpResponse response = null;    
                            HttpDelete httpDelete = new HttpDelete(url);    
                            response = httpClient.execute(httpDelete); 
        
                            String sResponse;
        
                            StringBuilder s = new StringBuilder();
        
                            while ((sResponse = reader.readLine()) != null) {
                                s = s.append(sResponse);
                            }
        
                            Log.v(tag, "Yo! Response recvd ["+s.toString()+"]");
                            return s.toString();
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                      return s.toString();
                }
        

        【讨论】:

        • 什么是“final_url”?您指的是 “url” 吗?您在哪里向请求写入附加数据?我看不出与这个问题有任何联系。
        【解决方案7】:

        您不能只使用addHeader() 方法吗?

        【讨论】:

        • 如上所述,您建议使用什么 addHeader() 方法?我的问题的两个答案似乎暗示了相同的方法,但除非我遗漏了什么,否则该方法不存在。
        • 看来你错过了,看看HTTPURLConnection的父母。URLConnection
        • 那个方法是addRequestHeader(),和addHeader()不一样..!
        • 编辑:该方法是 addRequestProperty(String field, String newValue) (因此与 addHeader() 不同)...此外,它要求我为我的数据命名 - 原始代码刷新没有任何此类名称的数据,所以我不确定如何使用它来获得相同的结果
        【解决方案8】:

        这是我的Delete 请求方法。

        简单地说就是post 请求加上额外的RequestProperty

        connection.setRequestProperty("X-HTTP-Method-Override", "DELETE");
        

        下面是完整的方法。

            public void executeDeleteRequest(String stringUrl, JSONObject jsonObject, String reqContentType, String resContentType, int timeout) throws Exception {
            URL url = new URL(stringUrl);
            HttpURLConnection connection = null;
            String urlParameters = jsonObject.toString();
            try {
                connection = (HttpURLConnection) url.openConnection();
        
                //Setting the request properties and header
                connection.setRequestProperty("X-HTTP-Method-Override", "DELETE");
                connection.setRequestMethod("POST");
                connection.setRequestProperty("User-Agent", USER_AGENT);
                connection.setRequestProperty(CONTENT_TYPE_KEY, reqContentType);
                connection.setRequestProperty(ACCEPT_KEY, resContentType);
        
        
                connection.setReadTimeout(timeout);
                connection.setConnectTimeout(defaultTimeOut);
        
                connection.setUseCaches(false);
                connection.setDoInput(true);
                connection.setDoOutput(true);
        
                // Send request
                DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
                wr.writeBytes(urlParameters);
                wr.flush();
                wr.close();
                responseCode = connection.getResponseCode();
                // To handle web services which server responds with response code
                // only
                try {
                    response = convertStreamToString(connection.getInputStream());
                } catch (Exception e) {
                    Log.e(Log.TAG_REST_CLIENT, "Cannot convert the input stream to string for the url= " + stringUrl + ", Code response=" + responseCode + "for the JsonObject: " + jsonObject.toString(), context);
                }
            } catch (
                    Exception e
                    )
        
            {
                if (!BController.isInternetAvailable(context)) {
                    IntentSender.getInstance().sendIntent(context, Constants.BC_NO_INTERNET_CONNECTION);
                    Log.e(Log.TAG_REST_CLIENT, "No internet connection", context);
                }
                Log.e(Log.TAG_REST_CLIENT, "Cannot perform the POST request successfully for the following URL: " + stringUrl + ", Code response=" + responseCode + "for the JsonObject: " + jsonObject.toString(), context);
                throw e;
            } finally{
        
                if (connection != null) {
                    connection.disconnect();
                }
            }
        
        }
        

        希望对你有所帮助。

        【讨论】:

          【解决方案9】:

          为了解决这个问题,发现没有支持的方法来发送包含标头数据的 HTTP DELETE 请求。

          解决方案是让客户端更改其 API 以接受标准 GET 请求,该请求指示该操作应为删除,其中包含要删除的项目的 ID。

          http://clienturl.net/api/delete/id12345
          

          【讨论】:

          • 这个答案不准确。您可以添加标题数据,而不是正文。问题是当你打电话给setDoOutput(true)
          • 将方法更改为 GET 是您能做的最糟糕的事情。
          • 发出 GET 请求来替换您的 DELETE 请求根本不是一个好习惯。稍后它会导致您遇到更多问题。
          • 即使答案不正确,也很容易将答案标记为回复。在打破投票记录欢呼声之前,您应该取消标记!
          猜你喜欢
          • 1970-01-01
          • 2010-11-06
          • 1970-01-01
          • 1970-01-01
          • 2011-07-07
          • 1970-01-01
          • 2013-06-09
          • 2010-10-06
          • 2017-01-23
          相关资源
          最近更新 更多