前言
最近有个需求要读取NAS中的数据,NAS是以共享文件夹的形式来提供数据的,需要通过java来调用,最开始使用的jcifs,后来发现jcfis只支持smb1协议,而NAS提供的数据要用smb2或者smb3协议来读取,最后只能使用smbj来读取了,但可惜的是,smbj中没有提供列出文件夹或者文件全路径的接口,这么简单的方法都没有,实在是太坑爹了,无奈之下,自己拓展了一个。
1 引用smbj
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>smbj</artifactId>
<version>0.10.0</version>
</dependency>
2 调用
@RequestMapping("/ReadNasFepk")
@ResponseBody
public void ReadNasFepk() throws IOException {
SMBClient client = new SMBClient();
//从配置文件读取用户名密码等
InputStream inStream = new FileInputStream(new File(resource));
Properties properties = new Properties();
properties.load(inStream);
String SHARE_DOMAIN = "domain";//固定值,无需改动
String SHARE_USER = properties.getProperty("user");//用户名
String SHARE_PASSWORD = properties.getProperty("pwd");//密码
String SHARE_SRC_DIR = properties.getProperty("dir");//共享的文件夹名
String ip = properties.getProperty("ip");//ip 如:123.123.123.123
Map<String,String> map=new HashMap<>();
try {
Connection connection = client.connect(ip);
AuthenticationContext ac = new AuthenticationContext(SHARE_USER, SHARE_PASSWORD.toCharArray(), SHARE_DOMAIN);
Session session = connection.authenticate(ac);
// 连接共享文件夹
DiskShare share = (DiskShare) session.connectShare(SHARE_SRC_DIR);
String fatherPath=share.getSmbPath().toString().replace("\\","/");
String sharePath="";
// 遍历文件列表,查找指定文件类型
ReadNasFepkRecurisive(fatherPath,sharePath,map,share);
infoLogger.info(map);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
//递归调用
public void ReadNasFepkRecurisive(String fatherPath,String sharePath,Map<String,String> map,DiskShare share){
//share.list("");即可列出文件夹下所有的文件夹和文件
//share.list("北京");即可列出北京文件夹下所有的文件夹和文件
//share.list("北京\朝阳区");即可列出北京\朝阳区文件夹下所有的文件夹和文件
List<FileIdBothDirectoryInformation> list=share.list(sharePath);
for (FileIdBothDirectoryInformation file : list) {
String filename=file.getFileName();
if (".".equals(filename) || "..".equals(filename)) {
continue;
}
if (EnumWithValue.EnumUtils.isSet(file.getFileAttributes(), FileAttributes.FILE_ATTRIBUTE_DIRECTORY)) {
//说明是文件夹
String sonPath=fatherPath+"/"+filename;
//下一级路径
sharePath= sharePath=="" ? filename : sharePath+"\\"+filename;
//递归读取
ReadNasFepkRecurisive(sonPath,sharePath,map,share);
//读取完后恢复上一级路径
if(sharePath.lastIndexOf("\\")!=-1){
sharePath=sharePath.substring(0,sharePath.lastIndexOf("\\"));
}else{
sharePath="";
}
}else{
//说明是文件
if(filename.endsWith(".fepk")){
//全路径
String path=fatherPath+"/"+filename;
//文件名
String name=filename.replace(".fepk","");
map.add(name,path);
infoLogger.info(name);
infoLogger.info(path);
}
}
}
}
3 总结
感觉smbj这个库没有jcfis好用,jcfis也有支持smb2和smb3协议的拓展库,叫做jcfis-ng,有空再研究吧,smbj不知是否可以在linux上用,因为它的文件夹分隔符使用的是“\”不是“/”,目前我只在windows上进行了测试,这个问题就留着有志之士解答吧。