java HttpURLConnection Already connected异常

java之HttpURLConnection 2019-12-30 阅读 344 评论 0

大家对HttpUrlConnection这个类并不陌生,它处于java.net包下的,是JDK支持的。主要用来服务器端发送Http请求。

问题

在安卓上,打算使用HttpURLConnection访问Web服务器,实现一个文件上传的功能,代码如下。

public static void post(String requestURL, String charset) throws IOException {
    String boundary = UUID.randomUUID().toString();
    URL url = new URL(requestURL);
    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
    httpConn.setUseCaches(false);
    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);
    OutputStream outputStream = httpConn.getOutputStream();
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
    httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);    // 出现异常
}

最后一行setRequestProperty设置header时,出现了java.lang.IllegalStateException: Already connected异常。

java.lang.IllegalStateException: Already connected
	at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:3122)
	at Test.post(Test.java:95)
	at Test.main(Test.java:80)

原因

查看了setRequestProperty的源代码,发现在设置请求头前,会判断是否请求是否已连接。

/**
 * Sets the general request property. If a property with the key already
 * exists, overwrite its value with the new value.
 *
 * NOTE: HTTP requires all request properties which can
 * legally have multiple instances with the same key
 * to use a comma-separated list syntax which enables multiple
 * properties to be appended into a single property.
 *
 * @param   key     the keyword by which the request is known
 *                  (e.g., "{@code Accept}").
 * @param   value   the value associated with it.
 * @throws IllegalStateException if already connected
 * @throws NullPointerException if key is null
 * @see #getRequestProperty(java.lang.String)
 */
public void setRequestProperty(String key, String value) {
    if (connected)
        throw new IllegalStateException("Already connected");
    if (key == null)
        throw new NullPointerException ("key is null");

    if (requests == null)
        requests = new MessageHeader();

    requests.set(key, value);
}

解决

调整一下顺序,将setRequestProperty一行移到 httpConn.getOutputStream() 前面,在HttpURLConnection未连接之前设置请求属性,即header头。

public static void post(String requestURL, String charset) throws IOException {
    String boundary = UUID.randomUUID().toString();
    URL url = new URL(requestURL);
    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
    httpConn.setUseCaches(false);
    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);
    httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    OutputStream outputStream = httpConn.getOutputStream();
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
}
最后更新 2020-01-06