文章目录
- 什么是SMB协议
- SMB与CIFS区别
- 为什么要使用SMB
- 如何对接SMB服务
- 如何用Java实现Smb文件传输
- SmbV1的实现
- 基于SmbV1的文件上传
- 基于SmbV1的文件下载
- 基于SmbV1的文件重命名
- 基于SmbV1的文件删除
- 基于SmbV1的文件查询
- SmbV2的实现
- 基于SmbV2的文件上传
- 基于SmbV2的文件下载
- 基于SmbV2的文件重命名
- 基于SmbV2的文件删除
- 基于SmbV2的文件查询
- SmbUtil包
- 通过项目Swagger进行文件传输测试
- 测试文件上传
- 测试文件下载
- 测试文件删除
- 测试文件查询
- 测试文件重命名
- Github链接
什么是SMB协议
SMB 是 Server Message Block 的缩写。它是一种网络文件共享协议,允许用户与远程计算机和服务器通信,使他们能够在网络上访问文件、目录、打印机和端口等资源。SMB 在 TCP/IP 协议栈的应用层(第 7 层)上操作,并使用 TCP/IP 的 445 端口。目前我们常见的共享文件方式基本都是支持SMB协议。
以下是 SMB 常用场景:
文件共享
:SMB 的主要用途之一是文件共享。SMB 允许多个用户访问和共享存储在远程服务器上的文件,就像它们在自己的本地设备上一样。这使得在网络中的协作和共享资源变得简单。打印机共享
:SMB 可用于共享网络上的打印机。用户可以将打印请求发送到 SMB 服务器,服务器处理请求并返回响应。资源访问
:SMB 使用户能够访问远程计算机和服务器上的资源,如目录、打印机和端口。这使用户能够执行打印、访问共享文件夹和使用网络服务等任务。远程访问
:SMB 允许用户远程访问网络上的文件和资源。这对于需要从不同位置访问共享文件并在项目中协作的远程工作者或团队成员特别有用[来源6]。网络驱动器映射
:SMB 使用户可以在其设备上映射网络驱动器,使其能够像访问本地存储的文件和文件夹一样访问远程服务器上的文件和文件夹。这为网络中的共享资源提供了便利的访问方式。
值得注意的是,SMB 协议有不同的版本,包括 SMB1、SMB2、SMB3 和 SMB3.02。每个版本都引入了新功能、改进和安全增强。建议使用与您的网络环境兼容的最新 SMB 协议版本,以获得更好的性能和安全性。
SMB与CIFS区别
SMB(Server Message Block,服务器消息块)和CIFS(Common Internet File System,通用互联网文件系统)都是网络文件共享协议,它们允许计算机之间通过网络共享文件、打印机等资源。然而,它们之间存在一些差异。
SMB 是一种文件共享协议,由 IBM 发明,自 20 世纪 80 年代中期以来一直存在。它的设计目的是让计算机在局域网(LAN)上读写远程主机上的文件。SMB 是一种通信协议,不是特定的软件应用程序。SMB 协议在 Windows 系统中广泛使用,也被其他操作系统支持。
CIFS 是 SMB 的一个方言,也就是说,CIFS 是微软创建的 SMB 协议的一个特定实现。CIFS 的设计目标与 SMB 相似,但具有微软特色。由于 CIFS 是 SMB 的一种形式,因此在讨论和应用中,它们可以互换使用。
虽然它们都是顶级协议,但在实现和性能调优方面仍然存在差异,因此它们有不同的名称。协议实现,如 CIFS 和 SMB,通常会以不同的方式处理文件锁定、局域网/广域网上的性能和文件的批量修改等问题。
总之,SMB 是一种网络文件共享协议,而 CIFS 是 SMB 协议的一个特定实现。在实际应用中,它们之间的差异主要在于实现和性能调优方面。现在,我们只需要使用 SMB 这个术语,因为现代存储系统在底层通常不再使用 CIFS,而是使用 SMB 2 或 SMB 3。
为什么要使用SMB
除了以上说到的常用场景,我们在项目中主要还是用来对接上下游存储文件使用到的共享网盘,进行文件传输与存储,一般会搭配ADFS(Active Directory Federation Services)进行身份验证和授权。
以下是我们真实项目的一些应用案例:
因为在我们公司申请一个NAS共享文件夹一天就可以搞定,而搭建一台SFTP服务器,要走的流程很多,并且NAS共享文件夹还可以直接映射到我们Window系统当作本地硬盘那样使用,用户不需要额外开发一个文件上传下载接口,只需要暴露SMB协议给对接的应用即可,所以很多个人用户是使用NAS共享文件夹来存储文件和跟团队成员在局域网内协作处理文件。像Macbook也有共享文件功能,可以通过SMB协议跟局域网内的服务进行文件共享。
如何对接SMB服务
目前主流的SMB版本都是SmbV2、SmbV3,但是还有一些老系统会使用SmbV1。在Java目前的第三方工具包,SmbV1和SmbV2及以上的对接方式是不兼容的,所以需要分开处理。
支持SmbV1:
- Jcifs
支持SmbV2及以上:
- jcifs-codelibs
- jcifs-ng
- smbj
本文主要会使用Jcifs和smbj这两个框架来分别对接SmbV1和SmbV2服务,本文末尾提供了Github链接,大家可以直接下载示例代码查看。
如何用Java实现Smb文件传输
我们项目中,对共享文件夹要实现的操作主要就是 增、删、改、查,对应的文件操作就是文件上传、文件下载、文件删除、文件改名、文件查询。
SmbV1的实现
第三方工具包版本
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
基于SmbV1的文件上传
public boolean upload(FileUploadDTO fileUploadDTO) throws IOException {
String remoteFolder = fileUploadDTO.getRemoteFolder();
String uploadFile = fileUploadDTO.getLocalFilePath();
String remoteHost = fileUploadDTO.getRemoteHost();
String account = fileUploadDTO.getAccount();
String psw = fileUploadDTO.getPassword();
String domain = fileUploadDTO.getDomain();
File source = new File(fileUploadDTO.getLocalFilePath());
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, account, psw);
String smbUrl = "smb://" + remoteHost + "/" + fileUploadDTO.getShareName() + "/" + remoteFolder + source.getName();
SmbFile smbFile = new SmbFile(smbUrl, auth);
try (FileInputStream fis = new FileInputStream(source);
SmbFileOutputStream smbfos = new SmbFileOutputStream(smbFile)) {
final byte[] b = new byte[16 * 1024];
int read;
while ((read = fis.read(b, 0, b.length)) > 0) {
smbfos.write(b, 0, read);
}
log.info("=======>File {} has been upload to {} successfully", uploadFile, fileUploadDTO.getRemoteFolder() + source.getName());
}
return true;
}
基于SmbV1的文件下载
public boolean download(FileDownloadDTO fileDownloadDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
String subFolder = fileDownloadDTO.getRemoteFolder();
String remoteHost = fileDownloadDTO.getRemoteHost();
String account = fileDownloadDTO.getAccount();
String psw = fileDownloadDTO.getPassword();
String domain = fileDownloadDTO.getDomain();
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, account, psw);
String smbUrl = "smb://" + remoteHost + "/" + fileDownloadDTO.getShareName() + "/" + subFolder;
SmbFile smbFolder = new SmbFile(smbUrl, auth);
SmbFile[] files = smbFolder.listFiles(new SmbFilenameFilter() {
@Override
public boolean accept(SmbFile dir, String name) throws SmbException {
return !name.endsWith(fileDownloadDTO.getFileExtension());
}
});
for (SmbFile file : files) {
String fileName = file.getName();
log.info("=======>File Name:{}", fileName);
log.info("=======>File lastModifiedTime:{}", file.getLastModified());
log.info("=======>Is file existed?:{}", file.exists());
//Check file pattern
if (!matchPattern(matchFileList, file, fileDownloadDTO.getFilePattern())) continue;
String localFilePath = fileDownloadDTO.getLocalFolder() + fileName;
String newFileName = fileName + fileDownloadDTO.getFileExtension();
// Download file from share drive
try (SmbFileInputStream sfis = new SmbFileInputStream(file);
FileOutputStream fos = new FileOutputStream(localFilePath)) {
byte[] b = new byte[16 * 1024];
int read;
while ((read = sfis.read(b, 0, b.length)) > 0) {
fos.write(b, 0, read);
}
log.info("=======>File {} has been downloaded to {} successfully", fileName, localFilePath);
}
// Rename file after download successfully
SmbFile newFile = new SmbFile(file.getParent() + newFileName, auth);
file.renameTo(newFile);
log.info("=======>File {} has been renamed to {} successfully", fileName, newFileName);
}
if (matchFileList.isEmpty()) {
throw new NotMatchFilesException("No any match files found, please check your file pattern!", null);
}
return true;
}
基于SmbV1的文件重命名
public boolean rename(FileRenameDTO fileRenameDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
String subFolder = fileRenameDTO.getRemoteFolder();
String remoteHost = fileRenameDTO.getRemoteHost();
String account = fileRenameDTO.getAccount();
String psw = fileRenameDTO.getPassword();
String domain = fileRenameDTO.getDomain();
String prefix = fileRenameDTO.getPrefix();
String newFileName = fileRenameDTO.getNewFileName();
String suffix = fileRenameDTO.getSuffix();
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, account, psw);
String smbUrl = "smb://" + remoteHost + "/" + fileRenameDTO.getShareName() + "/" + subFolder;
SmbFile smbFolder = new SmbFile(smbUrl, auth);
SmbFile[] files = smbFolder.listFiles();
for (SmbFile file : files) {
String fileName = file.getName();
log.info("=======>File Name:{}", fileName);
log.info("=======>File lastModifiedTime:{}", file.getLastModified());
log.info("=======>Is file existed?:{}", file.exists());
//Check file pattern
if (!matchPattern(matchFileList, file, fileRenameDTO.getFilePattern())) continue;
if (!ObjectUtils.isEmpty(newFileName)) {
newFileName = prefix + newFileName + suffix;
} else {
newFileName = prefix + fileName + suffix;
}
// Rename file after download successfully
SmbFile newFile = new SmbFile(file.getParent() + newFileName, auth);
file.renameTo(newFile);
log.info("=======>File {} has been renamed to {} successfully", fileName, newFileName);
}
if (matchFileList.isEmpty()) {
throw new NotMatchFilesException("No any match files found, please check your file pattern!", null);
}
return true;
}
基于SmbV1的文件删除
public boolean delete(FileDeleteDTO fileDeleteDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
String subFolder = fileDeleteDTO.getRemoteFolder();
String remoteHost = fileDeleteDTO.getRemoteHost();
String account = fileDeleteDTO.getAccount();
String psw = fileDeleteDTO.getPassword();
String domain = fileDeleteDTO.getDomain();
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, account, psw);
String smbUrl = "smb://" + remoteHost + "/" + fileDeleteDTO.getShareName() + "/" + subFolder;
SmbFile smbFolder = new SmbFile(smbUrl, auth);
SmbFile[] files = smbFolder.listFiles();
for (SmbFile file : files) {
String fileName = file.getName();
log.info("=======>File Name:{}", fileName);
log.info("=======>File lastModifiedTime:{}", file.getLastModified());
log.info("=======>Is file existed?:{}", file.exists());
//Check file pattern
if (!matchPattern(matchFileList, file, fileDeleteDTO.getFilePattern())) continue;
// Remove ".done" file from share drive
file.delete();
log.info("=======>File {} has been removed successfully", fileName);
}
if (matchFileList.isEmpty()) {
throw new NotMatchFilesException("No any match files found, please check your file pattern!", null);
}
return true;
}
基于SmbV1的文件查询
public List<String> search(FileSearchDTO fileSearchDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
String subFolder = fileSearchDTO.getRemoteFolder();
String remoteHost = fileSearchDTO.getRemoteHost();
String account = fileSearchDTO.getAccount();
String psw = fileSearchDTO.getPassword();
String domain = fileSearchDTO.getDomain();
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, account, psw);
String smbUrl = "smb://" + remoteHost + "/" + fileSearchDTO.getShareName() + "/" + subFolder;
SmbFile smbFolder = new SmbFile(smbUrl, auth);
SmbFile[] files = smbFolder.listFiles();
for (SmbFile file : files) {
String fileName = file.getName();
log.info("=======>File Name:{}", fileName);
log.info("=======>File lastModifiedTime:{}", file.getLastModified());
log.info("=======>Is file existed?:{}", file.exists());
//Check file pattern
if (!matchPattern(matchFileList, file, fileSearchDTO.getFilePattern())) continue;
}
return matchFileList;
}
SmbV2的实现
第三方工具包版本
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>smbj</artifactId>
<version>0.11.5</version>
</dependency>
基于SmbV2的文件上传
public boolean upload(Session session, FileUploadDTO fileUploadDTO) throws IOException {
Connection conn = null;
try (
DiskShare share = (DiskShare) session.connectShare(fileUploadDTO.getShareName());
) {
java.io.File source = new java.io.File(fileUploadDTO.getLocalFilePath());
//Upload file to remote share drive
SmbFileUtils.upload(source, share, fileUploadDTO.getRemoteFolder() + source.getName(), true);
log.info("=======>File {} has been upload to {} successfully", source.getName(), fileUploadDTO.getRemoteFolder() + source.getName());
//Close connection in the end
conn = session.getConnection();
} finally {
if (conn != null) {
conn.close(true);
}
}
return true;
}
基于SmbV2的文件下载
public boolean download(Session session, FileDownloadDTO fileDownloadDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
Connection conn = null;
try (
DiskShare share = (DiskShare) session.connectShare(fileDownloadDTO.getShareName());
) {
List<FileIdBothDirectoryInformation> fileList = share.list(fileDownloadDTO.getRemoteFolder());
for (int i = 0; i < fileList.size(); i++) {
FileIdBothDirectoryInformation fileInfo = fileList.get(i);
boolean isExisted = SmbFileUtils.isFileExisted(fileDownloadDTO.getRemoteFolder(), share, fileInfo);
if (!isExisted) {
log.info("File {} is invalid", fileInfo.getFileName());
continue;
}
//Check file pattern
if (!matchPattern(matchFileList, fileInfo, fileDownloadDTO.getFilePattern())) continue;
log.info("=======>File Name:{}", fileInfo.getFileName());
log.info("=======>File lastModifiedTime:{}", fileInfo.getLastWriteTime());
String remoteFilePath = fileDownloadDTO.getRemoteFolder() + fileInfo.getFileName();
String localFilePath = fileDownloadDTO.getLocalFolder() + fileInfo.getFileName();
String newFileName = fileDownloadDTO.getRemoteFolder() + fileInfo.getFileName() + fileDownloadDTO.getFileExtension();
//Download file from share drive
SmbFileUtils.download(remoteFilePath, share, localFilePath);
//Rename file after download successfully
if (fileDownloadDTO.isNeedRename()) {
SmbFileUtils.rename(remoteFilePath, share, newFileName, true);
}
log.info("=======>File {} has been downloaded to {} successfully", fileInfo.getFileName(), localFilePath);
}
//Close connection in the end
conn = session.getConnection();
} finally {
if (conn != null) {
conn.close();
}
}
if (matchFileList.isEmpty()) {
throw new NotMatchFilesException("No any match files found, please check your file pattern!", null);
}
return true;
}
基于SmbV2的文件重命名
public boolean rename(Session session, FileRenameDTO fileRenameDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
String prefix = fileRenameDTO.getPrefix();
String newFileName = fileRenameDTO.getNewFileName();
String suffix = fileRenameDTO.getSuffix();
Connection conn = null;
try (
DiskShare share = (DiskShare) session.connectShare(fileRenameDTO.getShareName());
) {
List<FileIdBothDirectoryInformation> fileList = share.list(fileRenameDTO.getRemoteFolder());
for (int i = 0; i < fileList.size(); i++) {
FileIdBothDirectoryInformation fileInfo = fileList.get(i);
boolean isExisted = SmbFileUtils.isFileExisted(fileRenameDTO.getRemoteFolder(), share, fileInfo);
if (!isExisted) {
log.info("File {} is invalid", fileInfo.getFileName());
continue;
}
//Check file pattern
if (!matchPattern(matchFileList, fileInfo, fileRenameDTO.getFilePattern())) continue;
log.info("=======>File Name:{}", fileInfo.getFileName());
log.info("=======>File lastModifiedTime:{}", fileInfo.getLastWriteTime());
String remoteFilePath = fileRenameDTO.getRemoteFolder() + fileInfo.getFileName();
if (!ObjectUtils.isEmpty(newFileName)) {
newFileName = fileRenameDTO.getRemoteFolder() + prefix + newFileName + suffix;
} else {
newFileName = fileRenameDTO.getRemoteFolder() + prefix + fileInfo.getFileName() + suffix;
}
//Rename file after download successfully
SmbFileUtils.rename(remoteFilePath, share, newFileName, true);
log.info("=======>File {} has been renamed to {} successfully", fileInfo.getFileName(), newFileName);
}
//Close connection in the end
conn = session.getConnection();
} finally {
if (conn != null) {
conn.close();
}
}
if (matchFileList.isEmpty()) {
throw new NotMatchFilesException("No any match files found, please check your file pattern!", null);
}
return true;
}
基于SmbV2的文件删除
public boolean delete(Session session, FileDeleteDTO fileDeleteDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
Connection conn = null;
try (
DiskShare share = (DiskShare) session.connectShare(fileDeleteDTO.getShareName());
) {
List<FileIdBothDirectoryInformation> fileList = share.list(fileDeleteDTO.getRemoteFolder(), "*");
for (int i = 0; i < fileList.size(); i++) {
FileIdBothDirectoryInformation fileInfo = fileList.get(i);
boolean isExisted = SmbFileUtils.isFileExisted(fileDeleteDTO.getRemoteFolder(), share, fileInfo);
if (!isExisted) {
log.info("File {} is invalid", fileInfo.getFileName());
continue;
}
//Check file pattern
if (!matchPattern(matchFileList, fileInfo, fileDeleteDTO.getFilePattern())) continue;
log.info("=======>File Name:{}", fileInfo.getFileName());
log.info("=======>File lastModifiedTime:{}", fileInfo.getLastWriteTime());
String remotePath = fileDeleteDTO.getRemoteFolder() + fileInfo.getFileName();
//Remove ".done" file from share drive
SmbFileUtils.remove(remotePath, share);
log.info("=======>File {} has been remove successfully", fileInfo.getFileName());
}
//Close connection in the end
conn = session.getConnection();
} finally {
if (conn != null) {
conn.close();
}
}
if (matchFileList.isEmpty()) {
throw new NotMatchFilesException("No any match files found, please check your file pattern!", null);
}
return true;
}
基于SmbV2的文件查询
public List<String> search(Session session, FileSearchDTO fileSearchDTO) throws IOException {
List<String> matchFileList = new ArrayList<String>();
Connection conn = null;
try (
DiskShare share = (DiskShare) session.connectShare(fileSearchDTO.getShareName());
) {
List<FileIdBothDirectoryInformation> fileList = share.list(fileSearchDTO.getRemoteFolder());
for (int i = 0; i < fileList.size(); i++) {
FileIdBothDirectoryInformation fileInfo = fileList.get(i);
boolean isExisted = SmbFileUtils.isFileExisted(fileSearchDTO.getRemoteFolder(), share, fileInfo);
if (!isExisted) {
log.info("File {} is invalid", fileInfo.getFileName());
continue;
}
//Check file pattern
if (!matchPattern(matchFileList, fileInfo, fileSearchDTO.getFilePattern())) continue;
}
//Close connection in the end
conn = session.getConnection();
} finally {
if (conn != null) {
conn.close();
}
}
return matchFileList;
}
SmbUtil包
public class SmbFileUtils extends SmbFiles {
/**
* Get sessionø
*
* @param remoteHost remote host
* @param account account
* @param password password
* @param domain account domain
* @return SMB Session
* @throws IOException
*/
public static Session getSession(String remoteHost, String account, String password, String domain) throws IOException {
SmbConfig config = SmbConfig.builder()
//automatically choose latest supported smb version
.withMultiProtocolNegotiate(true)
.withSigningRequired(false)
.withTimeout(40, TimeUnit.SECONDS)
.withReadTimeout(100, TimeUnit.SECONDS)
.withWriteTimeout(100, TimeUnit.SECONDS)
.withTransactTimeout(100, TimeUnit.SECONDS)
//must enable
.withEncryptData(true)
.build();
SMBClient client = new SMBClient(config);
Connection conn = client.connect(remoteHost);
AuthenticationContext ac = new AuthenticationContext(account, password.toCharArray(), domain);
return conn.authenticate(ac);
}
/**
* Copies local file to a destination path on the share
*
* @param share the share
* @param destPath the path to write to
* @param source the local File
* @param overwrite true/false to overwrite existing file
* @return the actual number of bytes that was written to the file
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static int upload(java.io.File source, DiskShare share, String destPath, boolean overwrite) throws IOException {
return copy(source, share, destPath, overwrite);
}
/**
* Download a file from the share
*
* @param sourcePath the source File read from share drive
* @param share the share
* @param destPath the path to write to
* @return the actual number of bytes that was written to the file
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static long download(String sourcePath, DiskShare share, String destPath) throws IOException {
long totalBytesRead = 0;
try (InputStream in = share.openFile(sourcePath,
EnumSet.of(AccessMask.GENERIC_READ),
null, SMB2ShareAccess.ALL,
SMB2CreateDisposition.FILE_OPEN,
null).getInputStream();
OutputStream out = new FileOutputStream((destPath))
) {
byte[] buffer = new byte[10240];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
}
return totalBytesRead;
}
/**
* Rename file
*
* @param sourcePath the source File read from share drive
* @param share the share
* @param newFilePath the new file name
* @param overwrite overwirte if exists
* @return the actual number of bytes that was written to the file
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static int rename(String sourcePath, DiskShare share, String newFilePath, Boolean overwrite) throws IOException {
int r = 0;
try (File sourceFile = share.openFile(sourcePath,
EnumSet.of(AccessMask.DELETE),
null,
SMB2ShareAccess.ALL,
SMB2CreateDisposition.FILE_OPEN,
null)) {
//rename files
sourceFile.rename(newFilePath, overwrite);
}
return r;
}
/**
* remove file from share drive
*
* @param sourcePath the file path read from
* @param share share drive
* @throws java.io.FileNotFoundException
* @throws java.io.IOException
*/
public static void remove(String sourcePath, DiskShare share) {
try (File sourceFile = share.openFile(sourcePath,
EnumSet.of(AccessMask.DELETE),
null,
SMB2ShareAccess.ALL,
SMB2CreateDisposition.FILE_OPEN,
null)) {
sourceFile.deleteOnClose();
}
}
/**
* Check if current file is existed
*
* @param remoteFolder remote folder
* @param share share name
* @param fileInfo file information
* @return
*/
public static boolean isFileExisted(String remoteFolder, DiskShare share, FileIdBothDirectoryInformation fileInfo) {
boolean flag;
try {
flag = share.fileExists(remoteFolder + fileInfo.getFileName());
} catch (Exception ex) {
log.debug("Exception found :", ex);
flag = false;
}
return flag;
}
}
通过项目Swagger进行文件传输测试
大家可以直接到Github查看https://github.com/EvanLeung08/eshare-smb-client-in-java
,上面有完整代码,本示例项目已经做了SmbV1和SmbV2版本的兼容。如果身边没有支持Smb协议的设备去测试,苹果用户也可以下载LANDrive
这个APP,在Ipad、Iphone、MacBook可以免费使用Smb功能进行文件传输或者使用Macbook本机自带的共享文件夹功能。本文使用LANDrive
作为SMB服务端进行测试。
启动服务后,输入
http://localhost:8080/swagger-ui/index.html
打开,可以看到以下API列表
测试文件上传
如果SMB服务端只支持SmbV1
,需要添加多一个参数"smbVersion":"1.0"
{
"remoteHost": "192.168.50.69",
"shareName": "LANdrive",
"domain": null,
"account": "user",
"password": "123456",
"remoteFolder": "test/",
"localFilePath": "/Users/evan/Downloads/Untitled video (4).mp4"
}
下图可以看到,我文件已经成功上传到SMB服务端
测试文件下载
如果SMB服务端只支持SmbV1
,需要添加多一个参数"smbVersion":"1.0"
{
"remoteHost": "192.168.50.69",
"shareName": "LANdrive",
"domain": null,
"account": "user",
"password": "123456",
"remoteFolder": "test/",
"localFolder": "/Users/evan/Downloads/",
"filePattern": ".*\\.mp4$",
"fileExtension": ".d",
"needRename": true
}
这里是通过正则表达式去匹配
下载成功会在本地看到对应文件,因为这里参数打开了文件后缀功能,所以这里服务端文件名也会变成xxx.d
。
测试文件删除
如果SMB服务端只支持SmbV1
,需要添加多一个参数"smbVersion":"1.0"
{
"remoteHost": "192.168.50.69",
"shareName": "LANdrive",
"domain": null,
"account": "user",
"password": "123456",
"remoteFolder": "test/",
"filePattern": "*"
}
这里是通过正则表达式去匹配
远程文件已经被成功删除
测试文件查询
如果SMB服务端只支持SmbV1
,需要添加多一个参数"smbVersion":"1.0"
{
"remoteHost": "192.168.50.69",
"shareName": "LANdrive",
"domain": null,
"account": "user",
"password": "123456",
"remoteFolder": "test/",
"filePattern": ".*\\.mp4$"
}
这里是通过正则表达式去匹配
如果查询到有匹配的文件,会成功显示在响应报文
测试文件重命名
如果SMB服务端只支持SmbV1
,需要添加多一个参数"smbVersion":"1.0"
{
"remoteHost": "192.168.50.69",
"shareName": "LANdrive",
"domain": null,
"account": "user",
"password": "123456",
"remoteFolder": "test/",
"filePattern": ".*\\.mp4$",
"prefix": "test_",
"suffix": ".d",
"newFileName": "after"
}
这里是通过正则表达式去匹配
远程服务端文件已经被成功改名
改名前
改名后
Github链接
https://github.com/EvanLeung08/eshare-smb-client-in-java