HttpClient模擬使用者登入,抓取伺服器檔案
需求說明:將兩個不相關的系統中的電子檔案合併,包含資料庫資訊(資料庫表格式各不相同,而且不能修改專案原始碼),並且每隔一段時間可以自動同步一次。之前是通過人工手動錄入,效率低而且容易遺漏。現在決定用HttpClient開發一個小專案來實現上述功能。
一、HttpClient簡單的介紹一下
HttpClient 是 Apache Jakarta Common 下的子專案,可以用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。官方站點:http://hc.apache.org/
Maven地址:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.5</version> </dependency>
HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程式需要直接通過 HTTP 協議來訪問網路資源。雖然在 JDK 的 java net包中
已經提供了訪問 HTTP 協議的基本功能,但是對於大部分應用程式來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子
專案,用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。HttpClient 已經應用在很多的專案中,
比如 Apache Jakarta 上很著名的另外兩個開源專案 Cactus 和 HTMLUnit 都使用了 HttpClient。現在HttpClient最新版本為 HttpClient 4.5.5(2018-06-14)。
二、使用HttpClient獲取網頁內容
import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; public class GetWebPageContent { /** * 抓取網頁資訊使用get請求 * @param args * @throws IOException */ public static void main(String[] args) throws IOException { //建立httpClient例項 CloseableHttpClient httpClient = HttpClients.createDefault(); //建立httpGet例項 HttpGet httpGet = new HttpGet("http://www.baidu.com"); CloseableHttpResponse response = httpClient.execute(httpGet); if (response != null){ HttpEntity entity = response.getEntity(); //獲取網頁內容 String result = EntityUtils.toString(entity, "UTF-8"); System.out.println("網頁內容:"+result); } if (response != null){ response.close(); } if (httpClient != null){ httpClient.close(); } } }
通過上述程式碼就可以抓取到baidu主頁的內容了,這裡需要注意的是抓取的部分網頁可能帶有中文會產生亂碼,在抓取到內容之後要進行相對應的編碼轉換。
三、模擬瀏覽器登入獲取到登入後的Session值
先通過瀏覽器F12在網頁中擷取到登入的請求地址,以及所需的引數列表List<NameValuePair>,這裡我專案用到的是地址是公司的內部的伺服器所以不需要驗證碼,如果需要驗證碼登入的話還需要解析驗證碼等操作,這裡就不詳細介紹了。
/**
* 獲得JesessioneID
* @param loginUrl 登入地址
* @param username 使用者名稱
* @param password 密碼
* @return JesessioneID
* @throws IOException IO異常
*/
public static String getJeseeion(String loginUrl, String username, String password) throws IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(loginUrl);
List<NameValuePair> nvp = new ArrayList<NameValuePair>();
nvp.add(new BasicNameValuePair("username", username));
nvp.add(new BasicNameValuePair("password", password));
String sCharSet = "UTF-8";
httpost.setEntity(new UrlEncodedFormEntity(nvp,sCharSet));
httpost.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
httpost.setHeader("Accept-Encoding", "gzip, deflate, sdch");
httpost.setHeader("Accept-Language", "zh-CN,zh;q=0.8");
httpost.setHeader("Connection", "keep-alive");
httpost.setHeader("Cache-Control", "max-age=0");
httpost.setHeader("Upgrade-Insecure-Requests", "1");
httpost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.61 Safari/537.36");
HttpResponse response = httpclient.execute(httpost);
httpost.abort();
if(response!=null)
{
String cookie = response.getFirstHeader("Set-Cookie").getValue();
String[] cookies = cookie.split(";");
String jession = cookies[0]; //本系統許可權只需要jessionid即可
System.out.println(jession);
return jession;
}
return null;
}
四、下載伺服器的檔案儲存到本地硬碟
將剛剛請求到的jesession值模擬儲存到請求頭中然後訪問伺服器中的檔案。
/**
* 根據url下載檔案,儲存到filepath中
* @param strUrl 檔案在伺服器中的地址
* @param filepath 儲存本地路徑
* @param jession 要模擬的Cookie值
* @return
*/
public static String download(String strUrl, String filepath, String jession) {
try {
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(strUrl);
if(jession!=null && !jession.equals("")){
httpget.setHeader("Cookie",jession);
}
HttpResponse response = client.execute(httpget);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
if (filepath == null)
filepath = getFilePath(response);
File file = new File(filepath);
file.getParentFile().mkdirs();
FileOutputStream fileout = new FileOutputStream(file);
/**
* 根據實際執行效果 設定緩衝區大小
*/
byte[] buffer=new byte[cache];
int ch = 0;
while ((ch = is.read(buffer)) != -1) {
fileout.write(buffer,0,ch);
}
is.close();
fileout.flush();
fileout.close();
System.out.println("檔案儲存成功,儲存路徑為:"+filepath);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 獲取response要下載的檔案的預設路徑
* @param response
* @return
*/
public static String getFilePath(HttpResponse response) {
String filepath = root + splash;
String filename = getFileName(response);
if (filename != null) {
filepath += filename;
} else {
filepath += getRandomFileName();
}
return filepath;
}
/**
* 獲取response header中Content-Disposition中的filename值
* @param response HttpResponse
* @return filename
*/
public static String getFileName(HttpResponse response) {
Header contentHeader = response.getFirstHeader("Content-Disposition");
String filename = null;
if (contentHeader != null) {
HeaderElement[] values = contentHeader.getElements();
if (values.length == 1) {
NameValuePair param = values[0].getParameterByName("filename");
if (param != null) {
try {
//filename = new String(param.getValue().toString().getBytes(), "utf-8");
//filename=URLDecoder.decode(param.getValue(),"utf-8");
filename = param.getValue();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return filename;
}
/**
* 獲取隨機檔名
* @return 檔名
*/
public static String getRandomFileName() {
return String.valueOf(System.currentTimeMillis());
}
執行一遍看看效果
public static void main(String[] args) throws IOException, URISyntaxException { //登入地址 String loginUrl = "http://192.168.3.215:8080/system/login/loginUserAjax"; //檔案下載連結 String strUrl = "http://192.168.3.215:8080/system/report/projectFileManage/downLoadFileAjax?aliasName=20180611223232.xlsx&directory=201806&fileName=1126.xlsx&r=1528778758118"; strUrl = new String(strUrl.getBytes("gbk"),"utf-8"); //存放路徑 String filepath = "D:\\test\\111.xlsx"; String username = "admin"; String password = "123456"; String sessionId = getJeseeion(loginUrl,username,password); download(strUrl,filepath,sessionId); }
控制檯輸出
JSESSIONID=D812E3E4E6E4A124079F154ADD160095 檔案儲存成功,儲存路徑為:D:\test\111.xlsx
本地檔案
模擬管理員登陸並從伺服器抓取電子檔案的功能大致實現了。