基于Smb协议实现网络文件传输

什么是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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
CIFS(Common Internet File System) 协议 CIFS 是一个新提出的协议,它使程序可以访问远程Internet计算机上的文件并要求此计算机的服务。CIFS 使用客户/服务器模式。客户程序请求远在服务器上的服务器程序为它提供服务。服务器获得请求并返回响应。CIFS是公共的或开放的SMB协议版本,并由Microsoft使用。SMB协议现在是局域网上用于服务器文件访问和打印的协议。象SMB协议一样,CIFS在高层运行,而不象TCP/IP协议那样运行在底层。CIFS可以看做是应用程序协议文件传输协议和超文本传输协议的一个实现SMB协议是基于TCP-NETBIOS下的,一般端口使用为139,445。 服务器信息块(SMB协议是一种IBM协议,用于在计算机间共享文件、打印机、串口等。SMB 协议可以用在因特网的TCP/IP协议之上,也可以用在其它网络协议如IPX和NetBEUI 之上。   SMB 一种客户机/服务器、请求/响应协议。通过 SMB 协议,客户端应用程序可以在各种网络环境下读、写服务器上的文件,以及对服务器程序提出服务请求。此外通过 SMB 协议,应用程序可以访问远程服务器端的文件、以及打印机、邮件槽(mailslot)、命名管道(named pipe)等资源。   在 TCP/IP 环境下,客户机通过 NetBIOS over TCP/IP(或 NetBEUI/TCP 或 SPX/IPX)连接服务器。一旦连接成功,客户机可发送 SMB 命令到服务器上,从而客户机能够访问共享目录、打开文件、读写文件,以及一切在文件系统上能做的所有事情。   从 Windows 95 开始,Microsoft Windows 操作系统(operating system)都包括了客户机和服务器 SMB 协议支持。Microsoft 为 Internet 提供了 SMB 的开源版本,即通用 Internet 文件系统 (CIFS)。与现有 Internet 应用程序如文件传输协议(FTP)相比, CIFS 灵活性更大。对于 UNIX 系统,可使用一种称为 Samba 的共享软件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值