今天在调试app的时候,用HttpURLConnection获取服务器数据的时候出现了java.io.FileNotFoundException异常,原因还不太明了,不过已经找到了解决方法。
由于我们的服务器数据有两种类型,一种是xml(请求带参数,即post方式),一种是json格式(请求参数直接附加在url后面,应该是get方式)。
之前请求这两种数据都是用同一种方式获取的即post方式,方法如下:
json数据地址为http://72.52.93.xxx/hdepg_data/dataForQuanQiuBo/2220143.js
/**
* post方式请求
* @param param 请求参数
* @param urlStr 请求地址
* @param contentType 内容格式
* @return
*/
public InputStream postMethod(String param, String urlStr,
String contentType) {
InputStream is = null;
try {
byte[] xmlData = param.getBytes("UTF-8");
URL url = new URL(urlStr);
URLConnection urlCon = url.openConnection();
urlCon.setDoOutput(false);
urlCon.setDoInput(true);
urlCon.setConnectTimeout(40000);
urlCon.setReadTimeout(40000);
urlCon.setUseCaches(false);
urlCon.setRequestProperty("Content-Type", contentType);
urlCon.setRequestProperty("Content-length",
String.valueOf(xmlData.length));
DataOutputStream printout = new DataOutputStream(
urlCon.getOutputStream());
printout.write(xmlData);
printout.flush();
printout.close();
is = urlCon.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Url connection failed!");
e.printStackTrace();
} catch (Exception e) {
Log.e(TAG, "Failed getting input stream!");
e.printStackTrace();
}
return is;
}
后来json数据换了一个地址:http://xxx.hanyastar.com/hdepg_data/dataForQuanQiuBo/xxxx.js,再用post方式请求数据的时候就出现java.io.FileNotFoundException异常了。感觉很奇怪,只是换了个地址而已,其他的操作都没变,为什么就不能成功访问了呢?
后来上网查了下,发现有人如是说:
原文地址:http://www.mikebai.com/html/2012-03/939.html
最近把机器刷到4.0了
跑了一下自己的app,发现下载xml文件部分抛出异常:java.io.FileNotFoundException: http://www.jpfocus.com/xxxx.xml
可是在2.3的系统却可以正常下载
我的代码:
URL url = new URL(urlstr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setRequestMethod("GET");
httpCon.setDoOutput(true);
httpCon.connect();
原因:
4.0中设置httpCon.setDoOutput(true),将导致请求以post方式提交,即使设置了httpCon.setRequestMethod("GET");
将代码中的httpCon.setDoOutput(true);删除即可
关于setDoOutput(true)
网上查到的解释是,设置true,表示你发送的请求,会把body的内容发送至server端,即POST和PUT才需要使用。GET完全可以不用设置。
难道新地址不支持post方式了?
于是我把请求方法修改了下:
public InputStream postMethodHanya(String param, String urlStr,
String contentType) {
InputStream is = null;
try {
byte[] xmlData = param.getBytes("UTF-8");
URL url = new URL(urlStr);
URLConnection urlCon = url.openConnection();
urlCon.setDoOutput(false);
urlCon.setDoInput(true);
urlCon.setConnectTimeout(40000);
urlCon.setReadTimeout(40000);
urlCon.setUseCaches(false);
// urlCon.setRequestProperty("Content-Type", contentType);
// urlCon.setRequestProperty("Content-length",
// String.valueOf(xmlData.length));
// // urlCon.setFixedLengthStreamingMode(xmlData.length);
// DataOutputStream printout = new DataOutputStream(
// urlCon.getOutputStream());
// printout.write(xmlData);
// printout.flush();
// printout.close();
is = urlCon.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Url connection failed!");
e.printStackTrace();
} catch (Exception e) {
Log.e(TAG, "Failed getting input stream!");
e.printStackTrace();
}
return is;
}
注释掉了post的body参数(如果不注释,而setDoOutput又设置为false的时候会报: java.net.ProtocolException: method does not support a request body: GET),setDoOutput设置为false(或者注释掉)。再用此方法获取新地址json数据就成功了。
虽然用get方式获取到了json数据,但是为什么会有两个地址的前后差异,现在还是没弄明白,在这里记录下。如果有大神知道还请赐教。
ps:setDoInput和setDoOutput的含义
- public void setDoInput(boolean doinput)将此 URLConnection 的 doInput 字段的值设置为指定的值。
- URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 true。
- public void setDoOutput(boolean dooutput)将此 URLConnection 的 doOutput 字段的值设置为指定的值。
- URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false。
- httpUrlConnection.setDoOutput(true);以后就可以使用conn.getOutputStream().write()
- httpUrlConnection.setDoInput(true);以后就可以使用conn.getInputStream().read();
- get请求用不到conn.getOutputStream(),因为参数直接追加在地址后面,因此默认是false。
- post请求(比如:文件上传)需要往服务区传输大量的数据,这些数据是放在http的body里面的,因此需要在建立连接以后,往服务端写数据。
- 因为总是使用conn.getInputStream()获取服务端的响应,因此默认值是true。