29

我的客户端 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 请求中?谢谢。

4

9 回答 9

32

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

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

于 2013-05-11T12:57:53.217 回答
7

这是HttpURLConnection, 在旧 Android 版本 (<=4.4) 上的限制。

虽然您可以选择使用HttpClient,但我不推荐它,因为它是一个旧库,有几个问题已从 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();
}
于 2016-07-11T22:29:51.340 回答
4

getOutputStream() 仅适用于具有正文的请求,例如 POST。在没有正文的请求上使用它,例如 DELETE,将引发 ProtocolException。相反,您应该使用 addHeader() 添加标头,而不是调用 getOutputStream()。

于 2012-04-26T17:56:17.757 回答
4

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

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

OKHttp 文档

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

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

conn.setDoOutput(true);

谢谢,希望它可以帮助。

于 2017-07-10T10:43:21.977 回答
4

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

    conn.setRequestProperty("X-HTTP-Method-Override", "DELETE");
    conn.setRequestMethod("POST");
于 2016-02-27T00:22:09.153 回答
2

试试下面的方法来调用 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();
        }
于 2015-05-13T08:18:10.867 回答
0

不能只用addHeader()方法吗?

于 2012-04-26T17:47:53.703 回答
0

这是我的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();
        }
    }

}

我希望它有所帮助。

于 2016-09-05T20:52:23.137 回答
-7

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

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

http://clienturl.net/api/delete/id12345
于 2013-01-26T12:16:55.420 回答