如何使用带有查询参数的HttpURLConnection PUT方法?

4

如何使用HttpURLConnection发送带有查询参数的PUT请求?

我正在尝试使用HttpURLConnection调用第三方REST API,但当我尝试在URL中传递参数时,它无法正常工作,并显示以下错误:

在映射注册表中找不到REST API Url

以下是目前对我无效的代码块:

    URL url;
    StringBuffer response = new StringBuffer();
    try
    {
        url = new URL(" http://thirdparty.com/party/api/v2/ksp/12/ks");
        HttpURLConnection httpURL = (HttpURLConnection) url.openConnection();
        httpURL.setDoOutput(true);
        httpURL.setRequestMethod("PUT");
        StringBuilder sbUrl = new StringBuilder("parameter1_id=");
        sbUrl.append(getParameter1Value())
             .append("&parameter2_id=")
             .append(getParameter2Value());
        final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(httpURL.getOutputStream()));
        writer.write(sbUrl.toString());
        writer.flush();
        writer.close();

        // throw the exception here in case invocation of web service
        if (httpURL.getResponseCode() != 200)
        {
            // throw exception
        }
        else
        {
            //SUCCESS
        }
    }
    catch (IOException e)
    {
    }

当我将这些参数作为 form-data 参数放在请求体中时,REST API 似乎会提供响应。

我的问题是如何使用 HttpURLConnection 使其工作?

我到目前为止尝试了什么? 我已经尝试将上面的代码修改为下面的样子,但它不起作用。

    try
    {
        url = new URL(" http://thirdparty.com/party/api/v2/ksp/12/ks");
        HttpURLConnection httpURL = (HttpURLConnection) url.openConnection();
        httpURL.setDoOutput(true);
        httpURL.setRequestMethod("PUT");
        httpURL.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + "----WebKitFormBoundarydklhfklsdfhlksh");
        dataOutputStream = new DataOutputStream(urlConnection.getOutputStream());

        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"parameter1_id\"");
        dataOutputStream.writeBytes("\r\n" + "parameter1Value" +"\r\n");
        dataOutputStream.writeBytes("--" + "----WebKitFormBoundarydklhfklsdfhlksh");
        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"parameter2_id\"");
        dataOutputStream.writeBytes("\r\n" + "parameter2Value" + "\r\n");
        dataOutputStream.writeBytes("--" + "----WebKitFormBoundarydklhfklsdfhlksh" + "--");
        dataOutputStream.flush();
        dataOutputStream.close();
        urlConnection.connect();
        // throw the exception here in case invocation of web service
        if (httpURL.getResponseCode() != 200)
        {
            // throw exception
        }
        else
        {
            //SUCCESS
        }
    }
    catch (IOException e)
    {
    }

编辑:它会抛出一个响应代码为500的错误。

编辑:仅澄清一下,我不是在尝试上传文件,而是在尝试将参数发送到BODY中(就像查询参数一样,而不是作为URL参数发送)。

非常感谢您对此提供任何指针或建议。


永远不要捕获异常而不处理它们,至少要记录日志。 - Jens
是的,我已经在我的代码中实现了,但为了给出实际代码块的图像,添加了这个空的“catch”块。 - N00b Pr0grammer
针对其他人收到“在映射注册表中找不到REST API Url”的错误信息:这个错误是由OpenText Content Server(OTCS)报告的,当您使用错误的动词调用某个端点时会出现此问题(例如,将一个期望只接受GET请求的端点用POST方式调用)。 - Andrew Spencer
2个回答

1
你谈到了“查询参数”和“URL中的参数”,但是你展示的两种方法都没有这样做。你的两种方法(尝试)在请求体中发送参数,也就是“实体”,而不是在URL中。虽然正文内容可能涉及应用程序级别的查询,但它们不是HTTP级别的查询字符串,也不是查询参数。你还询问“如何使这个与HttpURLConnection一起工作”,好像这是一个变化或差异,当事实上你的两次尝试已经使用了它。
你的第一次尝试看起来几乎正确。如果你设置了.setRequestProperty("Content-type", "application/x-www-form-urlencoded")(这不是自动的),并且你的值要么是URL编码的,要么不需要(没有保留字符)(根据服务器的不同,只有没有&或等号可能就足够了)。
你的第二次尝试也很接近。你需要在第一个部分之前写一个边界,并且对于每个部分,在Content-disposition: form-data; name="blah"之后,你需要一个CRLF来结束该头行,并且第二个CRLF来结束头块。(MIME多部分格式通常允许多个头行,尽管在这种情况下只需要一个。)最后边界后面应该跟着一个CRLF(在额外的--之后)。

当然,前提是您有正确的URL。如果没有正确的URL,任何操作都将无法正常工作。


如果我理解你的评论正确,那么我在问题中提出的两种方法都是将参数发送到请求正文中而不是URL中?(至少我认为第一个方法是将这些参数直接放在URL本身中发送的) - N00b Pr0grammer
尽管如此,目前两种方法都不起作用!我会尝试实现你的建议! - N00b Pr0grammer

0

使用HttpUrlConnection调用WebService的最佳方法 PUT方法

  ApiListener apilistener=null;

public void updateWorker()

    {

progressDialog = ProgressDialog.show(myContext, "Message",      
progressDialog.setCancelable(false);
progressDialog.setCanceledOnTouchOutside(false);

Thread runThread = new Thread(new Runnable() {

    @Override
    public void run() {

        HttpAppRequest http = new HttpAppRequest();


        try {

            JSONObject paramObject = new JSONObject();
            JSONObject dataObject = new JSONObject();

            dataObject.put("id", csId);

         }                       


        paramObject.put("data", dataObject);

            Log.e(AppConstants.TAG, "Param = " + paramObject.toString());

            AppResponse response = http.putJSONData(BASE_URL + "/updateapi", paramObject.toString(), true);

            if (response.getStatusCode() == 200) {

                String csUpdateResult = response.getContentData();
                Log.e(AppConstants.TAG, csUpdateResult);

                JSONObject updateObject = new JSONObject(csUpdateResult);


      Message completeMessage = handler.obtainMessage(1,    updateObject);
                completeMessage.sendToTarget();
            } else {
                handler.sendEmptyMessage(-1);
            }


        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

            String csMessage = myContext.getResources().getString(R.string.id_network_response_failure);
            Message completeMessage = handler.obtainMessage(0, csMessage);
            completeMessage.sendToTarget();
        }
    }
});

runThread.start();

}


   /*******************************************************************************************************/ Handler Api Response Here
               Handler handler= new Handler() {
@Override
public void handleMessage(Message inputMessage) {

    progressDialog.dismiss();

    if (inputMessage.what == 1) {
        try {

            JSONObject msgObject = (JSONObject) inputMessage.obj;

            if (msgObject.has("result")) {
                JSONObject resultObject = msgObject.getJSONObject("result");

                if (resultObject.has("status")) {
                    String csStatus = resultObject.getString("status");

                    if (csStatus.equalsIgnoreCase("success")) {

                        apilistener.onUpdate(resultObject.getString("msg"));

                    }
                } else {

                    if(resultObject.has("status"))
                    {
                                apilistener.onFailed(resultObject.getString("reason"));
                    }
                }


            }
        } catch (JSONException e) {
            CommonMethods.showMessageBox("", e.getMessage(), myContext);
        }

    } else if (inputMessage.what == 0) {
        String csMessage = (String) inputMessage.obj;
        CommonMethods.showMessageBox("", csMessage, myContext);
    }

}
       };

       //CallBack Listener to parent Activity/Fragment
      //User listener like this
       public interface ApiListener extends EventListener
      {
           void onSuccess(String msg);
           void onFaiulure(String msg);
        }

       public void setListener(ApiListener listener)
     {

           apilistener=listener;
                }


     }

你能更详细地解释一下这段代码吗?我对ApiListenerHttpAppRequest的理解不是很多! - N00b Pr0grammer
HttpAppRequest 只是处理请求的发送、接收和解析响应,您可以使用标准代码来完成这些操作。Listener 是回调到活动的接口,因为此请求是在单独的类和线程中进行的。它只是将回调发送到活动/片段。例如,当 apilistener.onSuccess(msg) 被调用时,活动可以从该类接收消息。 - Muhammad Hassaan
HttpAppRequest类已发布在新答案中。 - Muhammad Hassaan
1
我认为你完全误解了,我不是在尝试上传文件,而是只想发送两个参数。请再检查一下问题! - N00b Pr0grammer
1
你还没有回答问题。你使用了另一个API,并且不必要地引入了JSON。这样并没有以任何方式回答问题。 - user207421
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接