Java读取Windows环境共享文件夹(支持Win10/Win11等版本)
1、JCIFS介绍
JCIFS是使用纯Java开发的一个开源框架,通过smb协议访问远程文件夹。该框架同时支持Windows共享文件夹和Linux共享文件夹,不过,Linux共享文件夹需要安装Samba服务软件(官网:http://www.samba.org/)。
2、SMB协议
SMB协议(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。
SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源。
控制面板 -> 程序和功能 -> 启用或关闭Windows功能 -> 勾选SMB
3、设置共享文件夹
- 开启系统远程桌面功能:设置 -> 系统 -> 远程桌面 -> 启用远程桌面
- 创建或者选择一个文件夹
- 文件夹右键属性点击共享
- 选中的
everyone
选项,点击添加;设置级别权限,最后点击最下方的共享 - 文件夹右键属性,选择高级共享,点击权限,设置权限为完全控制,然后确定
- 打开网络和共享中心,点击更改高级共享设置,开启“启用文件和打印机共享”和“密码保护共享”,点击“保存更改”
- 在另一台电脑,
win+R
,输入mstsc
打开远程桌面,输入共享文件夹电脑的ip地址及用户名密码进行连接测试。
3.1、设置某些文件或文件夹禁止访问
用户 | 备注 |
Administrator | 系统权限最大的系统用户 |
Yohann | 我自己创建的用户 |
在这里我希望某些文件或者文件夹不让用户Yohann
访问,则可以进行如下设置:
- 文件夹:
- 文件:
4、java读取共享文件夹中的文件
4.1、添加smb协议依赖
<!--smb协议获取共享文件夹内容-->
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
4.2、创建连接,上传或获取文件内容
PS:由于工作业务没有涉及到下载远程文件,所以以下代码只有获取远程文件内容,如有需要可自行设计。
@Getter
@AllArgsConstructor
class Tuple2<T1, T2> {
private final T1 first;
private final T2 second;
public static <T1, T2> Tuple2<T1, T2> of(T1 t1,T2 t2){
return new Tuple2<>(t1,t2);
}
}
/**
* 上传本地文件 -> 远程windows共享文件夹下
*
* @param localFilePath 本地文件全路径
* @param ip 目标ip地址
* @param account 账号
* @param password 密码
* @param shareFolderName 目标地址共享文件夹名称
*/
public static void upLoadFile(String localFilePath, String ip, String account, String password,
String shareFolderName) {
InputStream in = null;
OutputStream out = null;
try {
File localFile = new File(localFilePath);
String remotePhotoUrl = "smb://" + account + ":" + password + "@" + ip + "/" + shareFolderName + "/"; //存放图片的共享目录
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS_");
SmbFile remoteFile = new SmbFile(remotePhotoUrl + "/" + fmt.format(new Date()) + localFile.getName());
// 尝试连接
remoteFile.connect();
log.info("connected to " + ip + " success!");
in = new BufferedInputStream(new FileInputStream(localFile));
out = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
byte[] buffer = new byte[4096];
// 读取长度
int len = 0;
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
// 刷新缓冲的输出流
out.flush();
log.info("文件:" + localFilePath.substring(localFilePath.lastIndexOf("\\") + 1) + " 上传至 " + remoteFile.getUncPath() + " 成功,目标文件名:" + remoteFile.getName());
} catch (Exception e) {
log.error("发生错误:" + e.getLocalizedMessage());
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception e) {
log.error("发生错误:流关闭失败");
}
}
}
/**
* 获取远程共享文件夹下的文件及内容
*
* @param ip 目标ip地址
* @param account 账号
* @param password 密码
* @param shareFolderName 目标地址共享文件夹名称 例:ShareFolder
* @param fileNameWithSuffix 共享文件夹下带后缀文件全路径 例:test/fyh/test.txt
* @return 文件字节数组
*/
public static byte[] getShareFile(String ip, String account, String password,
String shareFolderName, String fileNameWithSuffix) {
InputStream in = null;
ByteArrayOutputStream out = null;
try {
Tuple2<Boolean, SmbFile> tuple2 = testConnect(ip, account, password, shareFolderName, fileNameWithSuffix);
if (tuple2.getFirst()) {
SmbFile remoteFile = tuple2.getSecond();
// 创建文件流
in = new BufferedInputStream(new SmbFileInputStream(remoteFile));
out = new ByteArrayOutputStream((int) remoteFile.length());
// 读取文件内容
byte[] buffer = new byte[4096];
// 读取长度
int len = 0;
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
// 刷新缓冲的输出流
out.flush();
return out.toByteArray();
}
} catch (Exception e) {
log.error("下载远程文件出错:" + e.getLocalizedMessage());
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception e) {
log.error("发生错误:流关闭失败");
}
}
return new byte[]{};
}
/**
* 获取远程共享文件夹下的所有文件及内容
*
* @param ip 目标ip地址
* @param account 账号
* @param password 密码
* @param shareFolderName 目标地址共享文件夹名称 例:ShareFolder
* @return 共享文件夹下所有文件的名称及内容集合
*/
public static List<String> getShareFiles(String ip, String account, String password,
String shareFolderName) {
InputStream in = null;
ByteArrayOutputStream out = null;
List<String> list = new ArrayList<>();
try {
Tuple2<Boolean, SmbFile> tuple2 = testConnect(ip, account, password, shareFolderName, null);
if (tuple2.getFirst()) {
SmbFile remoteFile = tuple2.getSecond();
SmbFile[] smbFiles = remoteFile.listFiles();
if (smbFiles.length <= 0) {
log.error("共享文件夹下为空");
throw new RuntimeException("共享文件夹下为空");
}
for (SmbFile smbFile : smbFiles) {
if (smbFile.isDirectory()) {
recursionAddFile(list, in, out, smbFile);
continue;
}
// 创建文件流
in = new BufferedInputStream(new SmbFileInputStream(smbFile));
out = new ByteArrayOutputStream((int) smbFile.length());
// 读取文件内容
byte[] buffer = new byte[4096];
// 读取长度
int len = 0;
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
// 刷新缓冲的输出流
out.flush();
list.add(smbFile.getUncPath() + "\n" + out.toString());
}
return list;
}
} catch (Exception e) {
log.error("下载远程文件出错:" + e.getLocalizedMessage());
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception e) {
log.error("发生错误:流关闭失败");
}
}
return new ArrayList<>();
}
/**
* 递归获取文件夹下的文件及内容
*
* @param list 文件列表
* @param in 输入流
* @param out 输出流
* @param smbFile 文件夹
*/
public static void recursionAddFile(List<String> list, InputStream in, ByteArrayOutputStream out, SmbFile smbFile) {
try {
if (smbFile.isDirectory()) {
SmbFile[] smbFiles = smbFile.listFiles();
if (smbFiles.length > 0) {
for (SmbFile file : smbFiles) {
if (file.isDirectory()) {
recursionAddFile(list, in, out, file);
continue;
}
// 创建文件流
in = new BufferedInputStream(new SmbFileInputStream(file));
out = new ByteArrayOutputStream((int) file.length());
// 读取文件内容
byte[] buffer = new byte[4096];
// 读取长度
int len = 0;
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
// 刷新缓冲的输出流
out.flush();
list.add(file.getUncPath() + "\n" + out.toString());
}
}
}
} catch (Exception e) {
log.error(e.getLocalizedMessage());
}
}
/**
* 测试连接
*
* @param ip 目标ip地址
* @param account 账号
* @param password 密码
* @param shareFolderName 目标地址共享文件夹名称(如果不需要可以传null) 例:ShareFolder
* @param fileNameWithSuffix 共享文件夹下带后缀文件全路径(如果不需要可以传null) 例:test/fyh/test.txt
* @return 连接结果及返回值
*/
public static Tuple2<Boolean, SmbFile> testConnect(String ip, String account, String password,
String shareFolderName, String fileNameWithSuffix) {
if (StringUtils.isBlank(shareFolderName) && StringUtils.isNotBlank(fileNameWithSuffix)) {
throw new RuntimeException("请指定共享文件夹");
}
// 创建远程文件对象
String remotePhotoUrl = "smb://" + account + ":" + password + "@" + ip +
(StringUtils.isBlank(shareFolderName) ? "" : "/" + shareFolderName + "/") +
(StringUtils.isBlank(fileNameWithSuffix) ? "" : "/" + fileNameWithSuffix);
SmbFile remoteFile = null;
try {
remoteFile = new SmbFile(remotePhotoUrl);
// 尝试连接
remoteFile.connect();
log.info("connected to " + ip + " success!");
} catch (Exception e) {
log.error(e.getLocalizedMessage());
return Tuple2.of(false, null);
}
return Tuple2.of(true, remoteFile);
}
4.3、测试
public static void main(String[] args) {
// upLoadFile("D:\\test\\测试.txt", "10.18.110.126", "Administrator", "123456", "ShareFile");
// System.out.println(new String(getShareFile("10.18.110.126", "Administrator", "123456", "ShareFile", "哈哈/三级目录/四级/四级.txt")));
List<String> list = getShareFiles("10.18.110.126", "Yohann", "123456", "ShareFile");
list.forEach(System.out::println);
// Tuple2<Boolean, SmbFile> tuple2 = testConnect("10.18.110.126", "Administrator", "123456", null, null);
// System.out.println(tuple2.getFirst());
// Tuple2<Boolean, SmbFile> tuple2 = testConnect("10.18.110.126", "Administrator", "123456", "ShareFile", null);
// if (tuple2.getFirst()) {
// try {
// SmbFile[] files = tuple2.getSecond().listFiles();
// if (files.length <= 0) {
// log.error("null");
// }
// for (SmbFile file : files) {
// if (file.isDirectory()) {
// SmbFile[] smbFiles = file.listFiles();
// if (smbFiles.length <= 0) {
// log.error(file.getName() + " is null");
// }
// for (SmbFile smbFile : smbFiles) {
// System.out.println(smbFile.getName());
// }
// } else {
// continue;
// }
// }
// } catch (SmbException e) {
// e.printStackTrace();
// }
// }
}
4.4、结果