HttpURLConnection抛异常java.io.FileNotFoundException

今天在调试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的含义

  1. public void setDoInput(boolean doinput)将此 URLConnection 的 doInput 字段的值设置为指定的值。    
  2. URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 true。  
  3. public void setDoOutput(boolean dooutput)将此 URLConnection 的 doOutput 字段的值设置为指定的值。    
  4. URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false。    


  1. httpUrlConnection.setDoOutput(true);以后就可以使用conn.getOutputStream().write()  
  2. httpUrlConnection.setDoInput(true);以后就可以使用conn.getInputStream().read();  
  3.   
  4. get请求用不到conn.getOutputStream(),因为参数直接追加在地址后面,因此默认是false。  
  5. post请求(比如:文件上传)需要往服务区传输大量的数据,这些数据是放在http的body里面的,因此需要在建立连接以后,往服务端写数据。  
  6.   
  7. 因为总是使用conn.getInputStream()获取服务端的响应,因此默认值是true。  


  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
智能识别收货地址Java import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Encoder; class Demo { public static String calcAuthorization(String source, String secretId, String secretKey, String datetime) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { String signStr = "x-date: " + datetime + "\n" + "x-source: " + source; Mac mac = Mac.getInstance("HmacSHA1"); Key sKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), mac.getAlgorithm()); mac.init(sKey); byte[] hash = mac.doFinal(signStr.getBytes("UTF-8")); String sig = new BASE64Encoder().encode(hash); String auth = "hmac id=\"" + secretId + "\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"" + sig + "\""; return auth; } public static String urlencode(Map<?, ?> map) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); for (Map.Entry<?, ?> entry : map.entrySet()) { if (sb.length() > 0) { sb.append("&"); } sb.append(String.format("%s=%s", URLEncoder.encode(entry.getKey().toString(), "UTF-8"), URLEncoder.encode(entry.getValue().toString(), "UTF-8") )); } return sb.toString(); } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { //云市场分配的密钥Id String secretId = "xxxx"; //云市场分配的密钥Key String secretKey = "xxxx"; String source = "market"; Calendar cd = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Lo

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值