问题场景
在维护命令行客户端导入命令时,需要初始化文件大小信息,而通过
URLConnection connection = new URL(this.importUrl).openConnection();
long blobSize = connection.getContentLengthLong();
的方式获取ftp上文件的大小效果行不通,只好通过试探法去FTP上获取。
CODE
private static final String ftp = "FTP";
/**
* get size from http or ftp
* @param url
* @return
*/
public static long getSize(String url) {
URLConnection connection = new URL(url).openConnection();
connection.setRequestProperty("Accept-Encoding", "identity");
long blobSize;
if (StringUtils.startsWith(url.toLowerCase(), "ftp://")) {
blobSize = getSizeFromFtp(url);
if (blobSize == -1L) {
System.out.println("\nThe file does not exist in ftp.");
System.out.println("url: " + url);
System.exit(0);
}
} else {
blobSize = connection.getContentLengthLong();
}
return blobSize;
}
/**
* get file size from ftp
* @param url
* @return
* @throws IOException
*/
public static long getSizeFromFtp(String url) throws IOException {
long res = -1L;
FTPClient ftpClient = new FTPClient();
if (login(ftpClient, url)) {
JSONObject properties = getPropertyFromFtpUrl(url);
String ftpfilename = (String) properties.get("ftpfilename");
String charsetName = "GBK";
// 发送OPTS UTF8指令,尝试支持UTF-8
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
charsetName = "UTF-8";
}
FTPFile[] files = ftpClient.listFiles(new String(ftpfilename.getBytes(charsetName), "ISO-8859-1"));
if (files.length == 1) {
res = files[0].getSize();
}
}
ftpClient.disconnect();
return res;
}
/**
* ftp://javaa:javaa@172.168.2.212:21/test/javaa.txt
* ftp://用户名:密码@FTP服务器IP地址或域名:FTP命令端口/路径/文件名
* @param url url
* @return json object
*/
public static JSONObject getPropertyFromFtpUrl(String url) {
JSONObject obj = new JSONObject();
if (checkFtpUrl(url)) {
String username = null;
String password = null;
String hostname = null;
String port = "21";
String ftpfilename = null;
String userPwdIp = url.substring(6, url.indexOf('/', 6));
String ipAndPort;
if (userPwdIp.contains("@")) {
String userAndPwd = url.substring(6, url.lastIndexOf('@'));
if (userAndPwd.contains(":")) {
username = userAndPwd.split(":")[0];
password = userAndPwd.split(":")[1];
} else {
username = "anonymous";
}
ipAndPort = url.substring(url.lastIndexOf('@') + 1, url.indexOf('/', 6));
} else {
ipAndPort = userPwdIp;
}
if (ipAndPort.contains(":")) {
hostname = ipAndPort.split(":")[0];
port = ipAndPort.split(":")[1];
} else {
hostname = ipAndPort;
}
String fileNamePath = url.substring(url.indexOf('/', 6));
if (fileNamePath.contains("/")) {
ftpfilename = fileNamePath.substring(fileNamePath.lastIndexOf('/') + 1);
}
obj.put("username", username);
obj.put("password", password);
obj.put("hostname", hostname);
obj.put("port", port);
obj.put("ftpfilename", ftpfilename);
}
return obj;
}
/**
* 检验ftp的url合法性
* @param url ftp://javaa:javaa@172.168.2.212:21/test/javaa.txt
* @return boolean
*/
public static boolean checkFtpUrl(String url) {
return url.toLowerCase().startsWith("ftp://");
}
/**
* login for anonymous
* @param ftpClient client
* @param url url
* @return boolean
* @throws IOException
*/
public static boolean login(FTPClient ftpClient, String url) throws IOException {
JSONObject properties = getPropertyFromFtpUrl(url);
String hostname = (String) properties.get("hostname");
String port = (String) properties.get("port");
String username = (String) properties.get("username");
String password = (String) properties.get("password");
try {
ftpClient.connect(hostname, Integer.parseInt(port));
} catch (IOException e) {
e.printStackTrace();
}
ftpClient.setControlEncoding("UTF-8");
if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
if (isAnonymous(username, password)) {
username = ftp;
password = ftp;
}
if (!ftpClient.login(username, password)) {
throw new IOException("Wrong username or password!");
} else {
return true;
}
}
return false;
}
/**
* is it anonymous?
* @param username name
* @param password pwd
* @return boolean
*/
public static boolean isAnonymous(String username, String password) {
return ((username == null || username.equals("anonymous")) && password == null)
|| ((username != null && username.equals(ftp)) && password.equals(ftp));
}