需求:在網頁上預覽帶密碼的ftp伺服器上的圖片
最近遇到個需求,要在頁面上顯示ftp端的圖片,但是不要下載到本地。 思路一:從後台傳來圖片路徑,直接在img的src中寫入ftp圖片路徑,發現不顯示,百度後發現需要同時傳入ftp的使用者名稱和密碼,寫法如下:
<img src="ftp://bill:BillSanMa1030@test.3mkj.com/test.jpg" />
嘗試了一下,哇,顯示出來了,so easy,但是在chrome訪問,發現圖片沒有出現,控制台報錯了,點開連結如下:
意思是chrome從59版本後同一頁面禁止讀取不同源的資源,也就是http頁面不可以嵌入ftp的資源。嘗試了chrome54版本是可以顯示的。
思路二:沒辦法,胳膊擰不過大腿,扛不過google,只能另尋出路,想到從服務端擷取圖片後,讀取出來,轉成Base64格式傳到前台,
首先百度找到java從ftp擷取檔案的代碼,網上多得很, 再找到將圖片轉為Base64格式的代碼,也是一搜一大把 :
import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.codec.binary.Base64; import org.apache.commons.net.ftp.FTPFile;
FTPClient fc = new FTPClient();
// 串連ftp fc.connect("test.3mkj.com", 21);
// 登入 fc.login("bill", "BillSanMa1030");
// 設定編碼格式 fc.setControlEncoding("UTF-8");
String remoteAbsoluteFile = fs[0].getName(); remoteAbsoluteFile = new String(remoteAbsoluteFile.getBytes("UTF-8"), "ISO-8859-1");
// 獲得輸入資料流 InputStream in = fc.retrieveFileStream(remoteAbsoluteFile); byte[] bytes = new byte[in.available()]; int length = in.read(bytes);
String base64Image = new String(Base64.encodeBase64(bytes));
但是,驗證發現確實返回了一個Base64格式的字串,但是卻不是正確的圖片轉化,網上也找不到更詳細的資料,仔細研究後發現in.available()比實際檔案要小,查看FTPClient API發現retrieveFileStream的描述是“ 返回從其中一個指定的檔案從伺服器可以讀取的InputStream。”也就是說可能返回的並不是完整檔案的 InputStream,繼續查看API,發現有retrieveFile ( String remote, OutputStream local) ( 從伺服器檢索命名檔案並將其寫入給定的OutputStream。 ),嘗試使用 Output Stream ,於是把代碼修改為:
FTPFile[] fs = fc.listFiles();
// 獲得檔案大小
int size = (int) fs[0].getSize();
byte[] bytes = new byte[size];
ByteArrayOutputStream os = new ByteArrayOutputStream();
// 寫入輸出資料流
fc.retrieveFile(remoteAbsoluteFile,os);
bytes = os.toByteArray();
String base64Image = new String(Base64.encodeBase64(bytes));
問題解決~以上。