瀏覽器輸入網址從FTP服務上下載檔案
阿新 • • 發佈:2019-02-11
實現思路:請求伺服器拿到檔案二進位制資料,使用HttpServletResponse寫出。
第一步:連線linux伺服器上FTP(前提是伺服器上要先配置ftp服務)
需要匯入 org.apache.commons包
private static FTPClient getConnect(String chilPath) { FTPClient connect = new FTPClient(); ConfigUtil instance = ConfigUtil.getInstant(); try { connect.connect(instance.getValue(Constant.FTP_IP), Integer.valueOf(instance.getValue(Constant.FTP_PORT))); connect.login(instance.getValue(Constant.FTP_USERNAME), instance.getValue(Constant.FTP_PASSWORD)); connect.setFileType(FTPClient.BINARY_FILE_TYPE); if (!FTPReply.isPositiveCompletion(connect.getReplyCode())) { connect.disconnect(); } if (StringUtils.isEmpty(chilPath)) { connect.changeWorkingDirectory(instance .getValue(Constant.FTP_PATH)); } else { // 建立新的資料夾,FTP使用ISO8859-1編碼方式 String tempPath = new String( (instance.getValue(Constant.FTP_PATH) + chilPath) .getBytes("UTF-8"), "ISO-8859-1"); connect.makeDirectory(tempPath); connect.changeWorkingDirectory(tempPath); } } catch (Exception e) { LOG.error("create new connection ftp is err", e); } return connect; }
此方法作用是連線伺服器上的ftp服務,現實上傳下載的功能;
Constant.FTP_IP 是ftp ip地址
Constant.FTP_PORT 是ftp 埠號
Constant.FTP_USERNAME 是ftp 使用者名稱
Constant.FTP_PASSWORD 是ftp 密碼
此段程式碼中需要注意的地方有兩點:地址示例:/home/soft/ftp/userHeadIcon/123.png
1.ConfigUtl是一個獲取配置檔案的類,Constant.FTP_PATH是伺服器上的預設的一段地址(如:/home/soft/ftp/);
2.入參chilPath指的是在預設地址後的資料夾(如:userHeadIcon) ,可以為空
第二步:下載ftp上的檔案轉為二進位制
/** * 下載檔案 有子資料夾 * * @param fileName * 檔名 * @param chilPath * 子資料夾路徑 * @return */ public static byte[] downFile(String fileName, String chilPath) { FTPClient connect = getConnect(chilPath); return downFile(fileName, connect); } /** * 下載檔案 無子資料夾 * * @param fileName * 檔名 * @return */ public static byte[] downFile(String fileName) { FTPClient connect = getConnect(null); return downFile(fileName, connect); }
public static byte[] downFile(String fileName, FTPClient connect) {
InputStream in = null;
try {
FTPFile[] fs = connect.listFiles(fileName);
// 遍歷所有檔案,找到指定的檔案
for (FTPFile file : fs) {
if (file.getName().equals(fileName)) {
connect.setBufferSize(1024);
connect.setControlEncoding("UTF-8");
in = connect.retrieveFileStream(fileName);
byte[] b = ByteUtil.input2byte(in);
return b;
}
}
} catch (Exception e) {
LOG.error("downFile is err", e);
} finally {
try {
if (in != null) {
in.close();
}
closeFtp(connect);
} catch (IOException e) {
}
}
return null;
}
第三步:輸出二進位制檔案,讓瀏覽器下載
public Object downloadFile(String filePath, HttpServletResponse response ) {
// 子目錄地址
String childPath = FileUtil.getParentPath(filePath, 1);
// 檔名
String fileName = FileUtil.getFileNameByPath(filePath);
// 檔案字尾名
String fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);
try {
byte[] outPutStream = null;
if(childPath == null)
{
// 子目錄不存在
outPutStream = FtpUtil.downFile(fileName);
}else
{
outPutStream = FtpUtil.downFile(fileName, childPath);
}
if(outPutStream != null)
{
response.reset();
response.setContentType("application/" + fileSuffixName + ";" + "charset = UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.getOutputStream().write(outPutStream);
// 以上為一種
response.reset();
response.setContentType("text/html; charset=utf-8");
response.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(完整的檔名+字尾名),"utf-8");
response.getOutPutStream.write(outPutStream);
return ErrorCode.SUCCESS_CODE;
}
LOG.info("===========下載失敗,檔案不存在=========");
} catch (Exception e) {
e.printStackTrace();
LOG.error("download file is error :" + e.toString());
}
return ErrorCode.FILE_DOWNLOAD_FAIL;
}
/**
* 獲取指定目錄的父目錄
*
* @param path
* @param num
* @return
*/
public static String getParentPath(String path, int num) {
try {
// 先將\\替換成/
String tempPath = path.replace("\\", "/");
for (int i = 0; i < num; i++) {
if (tempPath.lastIndexOf("/") != -1) {
tempPath = tempPath.substring(0, tempPath.lastIndexOf("/"));
continue;
}
return null;
}
return StringUtils.isEmpty(tempPath) ? null : tempPath + "/";
} catch (Exception e) {
LOG.error("getParentPath is err,"
+ String.format("path:%s, num:%s", path, num));
}
return null;
}
/**
* 獲取指定目錄檔名
*
* @param path
* @return
*/
public static String getFileNameByPath(String path) {
// 先將\\替換成/
String tempPath = path.replace("\\", "/");
return path.substring(tempPath.lastIndexOf("/") + 1);
}
注意:downloadFile()方法中傳的filePath為示例userHeadIcon/123.png部分
昨天搞的時候,火狐瀏覽器下載的檔案都為file.do,谷歌瀏覽器下載的都為file.zip,查了一天的資料,說是apache不認docx,pptx,,xlsx等Microsoft Office 2007+的檔案格式,而這些檔案本身是zip壓縮檔案,所以被apache當作zip壓縮檔案發給瀏覽器了.......
最後想了一下,我傳給瀏覽器的只是檔案內容的二進位制,並沒有指定檔案的名字等資訊,所以開始從這方面下手。終於找到
response.reset(); //清除快取
response.setContentType("application/" +fileSuffixName + ";" +"charset = UTF-8"); //設定字符集和檔案字尾名
response.setHeader("Content-Disposition","attachment; filename=" +fileName); // 設定檔名稱
加上了這3句話,瀏覽器就能正確的顯示檔名了(沒有加這3句話時下載的檔案,瀏覽器預設為zip或do,但是將字尾名改正確還是可以開啟的)。
歡迎志同道合的朋友加入java討論群,討論下技術,順便交個朋友!群號:426090267