java實現下載網路伺服器上的附件/圖片到本地
阿新 • • 發佈:2019-01-03
新人小白一枚,記錄下工作中遇到的一點問題和解決方案。僅供自己以後複習參考之用。歡迎大神指導,交流。
剛開始學寫部落格,不好的地方請委婉的指出來哦。
先來說說需求背景
使用java來實現從網站網頁獲取內容(抓取網頁)。可能會遇到以下兩種情況(我暫時就只是遇到了這兩種情況)。1、java後臺程式可以通過外網直接下載
這個就不做過多的論述,直接原樣抓取過來,後臺通過java中的DOM操作,批量的將a標籤中的href屬性和img標籤中src屬性修改為絕對路徑即可,直接下載或者訪問。2、java後臺程式不能通過外網直接下載
這裡有存在兩種情況:第一種:通過瀏覽器直接訪問網站,可以正常下載,但是通過java後臺程式碼跳轉訪問卻不能下載附件/圖片。出現這種情況的原因是網站對不能下載的相關內容添加了防盜鏈。第二種:通過瀏覽器不能直接訪問,需要通過VPN / 伺服器代理 等方式,才能訪問的內網資源網站。以上兩種情況就是本文討論的重點,可以通過接下來即將介紹的一種方式統一解決。實際業務需求
功能實現程式碼
通過以上程式碼,就實現了將A中資料下載儲存到B中。以上程式碼也是我從網上找了好久才找到的,加上我自己實際中的需求比如新增代理,設定header等。/** * 儲存附件到本地並返回本地檔名 * @param fileUrl 附件網路地址 * @param suffix 附件字尾名 * @return 本地附件名稱 */ public String getLocalFileUrl(String fileUrl, String suffix ){ String localFileUrl = null; String fileName = null; try { Md5Util md5 = Md5Util.getInstance(); fileName = md5.string2string(fileUrl)+ "." +suffix; URL url = new URL(fileUrl); //設定代理 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("內網網路地址", 埠號)); //開啟連結 HttpURLConnection conn = (HttpURLConnection)url.openConnection(proxy); //新增header驗證資訊 conn.setRequestProperty("Proxy-Authorization", "使用者名稱:密碼"); conn.setRequestProperty("Host", "網址"); conn.setRequestProperty("Cookie", "XXXXXXXXX"); //設定請求方式為"GET" conn.setRequestMethod("GET"); //超時響應時間為5秒 conn.setConnectTimeout(5 * 1000); //通過輸入流獲取資料 InputStream inStream = conn.getInputStream(); //得到二進位制資料,以二進位制封裝得到資料,具有通用性 byte[] data = readInputStream(inStream); //new一個檔案物件用來儲存,預設儲存當前工程根目錄 HttpServletRequest request = ServletActionContext.getRequest(); //獲取伺服器快取目錄 String directoryURL = request.getSession().getServletContext().getRealPath("/"); //D:\workspace\.metadata\.me_tcat7\webapps\EducationalSystem\ // String directoryURL = "/home/........"; //線上環境linuxs此處我是用的是絕對路徑 //建立本地檔案儲存目錄 File fileMkdir = new File(directoryURL + "/cacheFile/"+supportSchoolId()); if(!fileMkdir.exists()){ fileMkdir.mkdirs(); } localFileUrl = fileMkdir + "/" + fileName; //檔案路徑 File localFile = new File(localFileUrl); if(!localFile.exists()){ //建立檔案 localFile.createNewFile(); } //建立輸出流 FileOutputStream outStream = new FileOutputStream(localFile); //寫入資料 outStream.write(data); //關閉輸出流 outStream.close(); } catch (Exception e) { e.printStackTrace(); } return fileName; } public byte[] readInputStream(InputStream inStream) throws Exception{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); //建立一個Buffer字串 byte[] buffer = new byte[1024]; //每次讀取的字串長度,如果為-1,代表全部讀取完畢 int len = 0; //使用一個輸入流從buffer裡把資料讀取出來 while( (len=inStream.read(buffer)) != -1 ){ //用輸出流往buffer裡寫入資料,中間引數代表從哪個位置開始讀,len代表讀取的長度 outStream.write(buffer, 0, len); } //關閉輸入流 inStream.close(); //把outStream裡的資料寫入記憶體 return outStream.toByteArray(); }