HttpUrlConnection 基础使用
一个支持HTTP特定功能的URLConnection。
使用这个类遵循以下模式:
1.通过调用URL.openConnection()来获得一个新的HttpURLConnection对象,并且将其结果强制转换为HttpURLConnection.
2.准备请求。一个请求主要的参数是它的URI。请求头可能也包含元数据,例如证书,首选数据类型和会话cookies.
3.可以选择性的上传一个请求体。HttpURLConnection实例必须设置setDoOutput(true),如果它包含一个请求体。通过将数据写入一个由getOutStream()返回的输出流来传输数据。
4.读取响应。响应头通常包含元数据例如响应体的内容类型和长度,修改日期和会话cookies。响应体可以被由getInputStream返回的输入流读取。如果响应没有响应体,则该方法会返回一个空的流。
5.关闭连接。一旦一个响应体已经被阅读后,HttpURLConnection 对象应该通过调用disconnect()关闭。断开连接会释放被一个connection占有的资源,这样它们就能被关闭或再次使用。
从上面的话以及最近的学习可以总结出:
关于HttpURLConnection的操作和使用,比较多的就是GET和POST两种了
主要的流程:
创建URL实例,打开URLConnection
URL url=new URL("http://www.baidu.com"); HttpURLConnection connection= (HttpURLConnection) url.openConnection();
设置连接参数
常用方法:
setDoInput
setDoOutput
setIfModifiedSince:设置缓存页面的最后修改时间(参考自:http://blog.****.net/stanleyqiu/article/details/7717235)
setUseCaches
setDefaultUseCaches
setAllowUserInteraction
setDefaultAllowUserInteraction
setRequestMethod:HttpURLConnection默认给使用Get方法
设置请求头参数
常用方法:
setRequestProperty(key,value)
addRequestProperty(key,value)
setRequestProperty和addRequestProperty的区别就是,setRequestProperty会覆盖已经存在的key的所有values,有清零重新赋值的作用。而addRequestProperty则是在原来key的基础上继续添加其他value。
常用设置:
设置请求数据类型:
connection.setRequestProperty("Content-type","application/x-javascript->json");//json格式数据 connection.addRequestProperty("Content-Type","application/x-www-form-urlencoded");//默认浏览器编码类型,http://www.cnblogs.com/taoys/archive/2010/12/30/1922186.html connection.addRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);//post请求,上传数据时的编码类型,并且指定了分隔符 Connection.setRequestProperty("Content-type", "application/x-java-serialized-object");// 设定传送的内容类型是可序列化的java对象(如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
connection.addRequestProperty("Connection","Keep-Alive");//设置与服务器保持连接 connection.addRequestProperty("Charset","UTF-8");//设置字符编码类型
连接并发送请求
connect
getOutputStream
在这里getOutStream会隐含的进行connect,所以也可以不调用connect
获取响应数据
getContent (https://my.oschina.net/zhanghc/blog/134591)
getHeaderField:获取所有响应头字段
getInputStream
getErrorStream:若HTTP响应表明发送了错误,getInputStream将抛出IOException。调用getErrorStream读取错误响应。
实例:
get请求:
public static String get(){
String message="";
try {
URL url=new URL("http://www.baidu.com");
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5*1000);
connection.connect();
InputStream inputStream=connection.getInputStream();
byte[] data=new byte[1024];
StringBuffer sb=new StringBuffer();
int length=0;
while ((length=inputStream.read(data))!=-1){
String s=new String(data, Charset.forName("utf-8"));
sb.append(s);
}
message=sb.toString();
inputStream.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
post请求:
public static String post(){
String message="";
try {
URL url=new URL("http://119.29.175.247/wikewechat/Admin/Login/login.html");
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setConnectTimeout(30000);
connection.setReadTimeout(30000);
connection.setRequestProperty("Content-type","application/x-javascript->json");
connection.connect();
OutputStream outputStream=connection.getOutputStream();
StringBuffer sb=new StringBuffer();
sb.append("email=");
sb.append("[email protected]&");
sb.append("password=");
sb.append("1234&");
sb.append("verify_code=");
sb.append("4fJ8");
String param=sb.toString();
outputStream.write(param.getBytes());
outputStream.flush();
outputStream.close();
Log.d("ddddd","responseCode"+connection.getResponseCode());
InputStream inputStream=connection.getInputStream();
byte[] data=new byte[1024];
StringBuffer sb1=new StringBuffer();
int length=0;
while ((length=inputStream.read(data))!=-1){
String s=new String(data, Charset.forName("utf-8"));
sb1.append(s);
}
message=sb1.toString();
inputStream.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
下载文件或图片到外部存储:
public boolean isExternalStorageWritable(){
String state= Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)){
return true;
}
return false;
}
private void doSDCard(){
if (isExternalStorageWritable()){
new Thread(){
@Override
public void run() {
try {
File file=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
if (!file.exists()){
file.mkdirs();
}
File newFile=new File(file.getPath(),System.currentTimeMillis()+".jpg");
// newFile.createNewFile();
URL url = new URL("http://images.****.net/20150817/1.jpg");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream inputStream = connection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(newFile.getAbsolutePath());
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes);
}
inputStream.close();
fileOutputStream.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}else {
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setMessage("外部存储不可用!");
builder.create().show();
}
}
post上传图片和表单数据:
public static String uploadFile(File file){
String message="";
String url="http://119.29.175.247/uploads.php";
String boundary="7786948302";
Map<String ,String> params=new HashMap<>();
params.put("name","user");
params.put("pass","123");
try {
URL url1=new URL(url);
HttpURLConnection connection= (HttpURLConnection) url1.openConnection();
connection.setRequestMethod("POST");
connection.addRequestProperty("Connection","Keep-Alive");
connection.addRequestProperty("Charset","UTF-8");
connection.addRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在
// http正文内,因此需要设为true, 默认情况下是false;
connection.setDoOutput(true);
//设置是否从httpUrlConnection读入,默认情况下是true;
connection.setDoInput(true);
// Post 请求不能使用缓存 ?
connection.setUseCaches(false);
connection.setConnectTimeout(20000);
DataOutputStream dataOutputStream=new DataOutputStream(connection.getOutputStream());
FileInputStream fileInputStream=new FileInputStream(file);
dataOutputStream.writeBytes("--"+boundary+"\r\n");
// 设定传送的内容类型是可序列化的java对象
// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\""
+ URLEncoder.encode(file.getName(),"UTF-8")+"\"\r\n");
dataOutputStream.writeBytes("\r\n");
byte[] b=new byte[1024];
while ((fileInputStream.read(b))!=-1){
dataOutputStream.write(b);
}
dataOutputStream.writeBytes("\r\n");
dataOutputStream.writeBytes("--"+boundary+"\r\n");
try {
Set<String > keySet=params.keySet();
for (String param:keySet){
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\""
+encode(param)+"\"\r\n");
dataOutputStream.writeBytes("\r\n");
String value=params.get(param);
dataOutputStream.writeBytes(encode(value)+"\r\n");
dataOutputStream.writeBytes("--"+boundary+"\r\n");
}
}catch (Exception e){
}
InputStream inputStream=connection.getInputStream();
byte[] data=new byte[1024];
StringBuffer sb1=new StringBuffer();
int length=0;
while ((length=inputStream.read(data))!=-1){
String s=new String(data, Charset.forName("utf-8"));
sb1.append(s);
}
message=sb1.toString();
inputStream.close();
fileInputStream.close();
dataOutputStream.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
private static String encode(String value) throws UnsupportedEncodingException {
return URLEncoder.encode(value,"UTF-8");
}
这里需要指出:
通过chrome的开发工具截取的头信息可以看到:
通过post上传数据时,若除了文本数据以外还要需要上传文件,则需要在指定每一条数据的Content-Disposition,name,若是文件还要指明filename,并在每条数据传输的后面用“--”加上boundary隔开,并且需要在第四行用“\r\n”换行符隔开,在最后一行也要用“--”加上boundary加上“--”隔开,否则会导致文件上传失败!
补充:
对于URLConnection,获取响应体数据的方法包括getContent和getInputStream
getInputStream上面已经提到,对于getContent的用法如下:
1、重写ContentHandler
2、实现ContentHandlerFactory接口,在createContentHandler方法中将重写的ContentHandler实例作为返回值返回
3、在HttpURLConnection.setContentHandlerFactory中实例化ContentHandlerFactory实例
代码如下:
public class ContentHandlerFactoryImpl implements ContentHandlerFactory {
@Override
public ContentHandler createContentHandler(String mimetype) {
if (mimetype==null){
return new ContentHandlerImpl(false);
}
return new ContentHandlerImpl(true);
}
class ContentHandlerImpl extends ContentHandler{
private boolean transform=false;
public ContentHandlerImpl(boolean transform){
this.transform=transform;
}
@Override
public Object getContent(URLConnection urlc) throws IOException {
if (!transform){
return urlc.getInputStream();
}else {
String encoding=getEncoding(urlc.getHeaderField("Content-Type"));
if (encoding==null){
encoding="UTF-8";
}
BufferedReader reader=new BufferedReader(new InputStreamReader(urlc.getInputStream(),encoding));
String tmp=null;
StringBuffer content=new StringBuffer();
while ((tmp=reader.readLine())!=null){
content.append(tmp);
}
return content.toString();
}
}
}
private String getEncoding(String contentType){
String [] headers=contentType.split(";");
for (String header:headers){
String [] params=header.split("=");
if (params.length==2){
if (params[0].equals("charset")){
return params[1];
}
}
}
return null;
}
}
public static String post(){
String message="";
URL url= null;
try {
url = new URL("http://127.0.0.1/test.php");
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setConnectTimeout(5*1000);
HttpURLConnection.setContentHandlerFactory(new ContentHandlerFactoryImpl());
connection.setRequestProperty("ContentType","application/x-www-form-urlencoded");
OutputStream outputStream=connection.getOutputStream();
StringBuffer stringBuffer=new StringBuffer();
stringBuffer.append("user[name]=");
stringBuffer.append("user");
stringBuffer.append("&user[pass]=");
stringBuffer.append("123");
outputStream.write(stringBuffer.toString().getBytes());
outputStream.flush();
outputStream.close();
Log.d("HttpUtil","responseMessage"+connection.getResponseMessage());
Map<String ,List<String >> map=connection.getHeaderFields();
Set<String> set=map.keySet();
for (String key:set){
List<String > list=map.get(key);
for (String value:list){
Log.d("HttpUtil","key="+key+" value="+value);
}
}
message= (String) connection.getContent();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}