HttpUrlConnection 基礎使用


From https://developer.android.com/reference/java/net/HttpURLConnection.html

HttpUrlConnection:

A URLConnection with support for HTTP-specific features. See the spec for details.

Uses of this class follow a pattern:

  1. Obtain a new HttpURLConnection by calling URL.openConnection() and casting the result to HttpURLConnection.
  2. Prepare the request. The primary property of a request is its URI. Request headers may also include metadata such as credentials, preferred content types, and session cookies.
  3. Optionally upload a request body. Instances must be configured with setDoOutput(true) if they include a request body. Transmit data by writing to the stream returned by getOutputStream().
  4. Read the response. Response headers typically include metadata such as the response body's content type and length, modified dates and session cookies. The response body may be read from the stream returned by getInputStream(). If the response has no body, that method returns an empty stream.
  5. Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused.

中文釋義:

一個支持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.csdn.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("409947972@qq.com&");
            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.csdn.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;
    }
復制代碼

參考自:https://my.oschina.net/zhanghc/blog/134591


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM