2015年12月16日 星期三

[Java] download file from HTTP (HTTP status)

最近發現一個從http下載檔案的程式出現了問題,
(其實常常發生XD, 因為http下載檔案的URL可能常常被變更, 所以只要下載有問題時, 都會第一時間照慣例去檢查URL有沒有異動)

但是這次URL變更, 只是從http改成https, 只是多了s讓我找了好苦阿(這時候就覺得瀏覽器聰明多了, 會自己去導向https)
不過呢, 程式有寫try catch, 理應會回傳錯誤訊息, 但是程式卻沒catch到而讓它pass,
經過debug檢查後, 才發現它download下來的是一個"空"的檔案, 所以程式認為有download成功才讓它pass吧!?

我是在程式裡面加了get HTTP status來debug, 發現這case的HTTP status是301(不是常見的403, 404)
這類status似乎是不會被catch!?

boolean downloadUrlFile(String urlpath, String filepath){
 try {
   String proxyURL="proxy.google.com.tw";
   String proxyPort="3128";
   SocketAddress sa = new InetSocketAddress( proxyURL , Integer.parseInt( proxyPort ) );
   Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
   URL url = new URL(urlpath);
   //URLConnection conn = url.openConnection(proxy);
   HttpURLConnection conn = (HttpURLConnection)url.openConnection(proxy);
   conn.setConnectTimeout(60000); //60sec, default: 15sec
   conn.setReadTimeout(90000); //90sec, default: 60sec
   conn.connect();
   
   /* Check Http Status*/
   int status = conn.getResponseCode();
   System.out.println(status);
   switch (status) {
   case java.net.HttpURLConnection.HTTP_GATEWAY_TIMEOUT://504
       System.out.println("連線網址逾時!");
       break;
   case java.net.HttpURLConnection.HTTP_FORBIDDEN://403
       System.out.println("連線網址禁止!");
       break;
   case java.net.HttpURLConnection.HTTP_INTERNAL_ERROR://500
       System.out.println("連線網址錯誤或不存在!");
       break;
   case java.net.HttpURLConnection.HTTP_NOT_FOUND://404
       System.out.println("連線網址不存在!");
       break;
   case java.net.HttpURLConnection.HTTP_OK:
       System.out.println("OK!");
       break;
   }
   
   java.io.BufferedInputStream in = new java.io.BufferedInputStream(conn.getInputStream());      
   java.io.FileOutputStream fos = new java.io.FileOutputStream(filepath);
   java.io.BufferedOutputStream bout = new BufferedOutputStream(fos,1024);
   byte[] data = new byte[1024];
   int x=0;
   while((x=in.read(data,0,1024))>=0)
   {
     bout.write(data,0,x);
   }
   bout.close();
   in.close();
 }catch (Exception e) {
   e.printStackTrace();
   return false;
 }
 return true;
}