最近在做一个远程FTP和SFTP相关的需求,开发SFTP使用的是com.jcraft.jsch包,版本是0.1.54。
废话少说,在进行SFTP文件搜索功能开发时,需要通过文件的绝对路径调用API中的 ls方法进行查询,此方法内容过长,只截取了部分。
当path中不含有 * 或者 ?号时,文件可以按照理想状态查询出来,但如果路径中存在以上两个符号(通配符)或其中之一,查询的结果就不正确了。原因在于this.isPattern方法,进入到方法的最底层可以看到,当path中含有 * 或者 ?字符时,方法返回true。而当pattern_has_wildcard为true时,该方法会将path中的 * 和 ?当作通配符处理,而不是当作路径去处理。
举个例子:你需要搜索 /home/sftp/123? 该路径下的的文件夹和文件,因为路径中含有 ?,正常来讲应该会去搜索123?下面的内容,但实际情况是搜索/home/sftp路径下与123?相匹配的内容,所以当路径中含有通配符时需要进行特殊处理,如何处理还是看isPattern方法,当路径中含有转义符时,并且转义符后面还有字符,i会增加两次,即会跳过转义字符后面字符的判断,所以解决办法就是在调用API之前,先对path进行contains()判断,如果含有通配符的话需要在通配符前加上转义字符。
private boolean isPattern(byte[] path){
int length=path.length;
int i=0;
while(i<length){
if(path[i]=='*' || path[i]=='?')
return true;
if(path[i]=='\\' && (i+1)<length)
i++;
i++;
}
return false;
}
最后附上处理方法:
private String pathHandler(String path) {
List<Byte> byteArr = Lists.newArrayListWithCapacity(path.length());
for(byte b : path.getBytes(StandardCharsets.UTF_8)) {
if (b == 42 || b == 63) {
byteArr.add((byte)92);
}
byteArr.add(b);
}
byte[] bytes = new byte[byteArr.size()];
for (int i = 0; i < byteArr.size(); i++) {
bytes[i] = byteArr.get(i);
}
return new String(bytes, StandardCharsets.UTF_8);
}