java HttpURLConnection Already connected异常
大家对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);
}