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

news2024/12/23 18:10:02

文章目录

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/677961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面向开发人员的 ChatGPT 提示词教程中文版 - ChatGPT 版

面向开发人员的 ChatGPT 提示词教程中文版 - ChatGPT 版 1. 指南1-1. 提示的指南1-2. 配置1-3. 提示语原则原则 1: 写出清晰而具体的指示技巧 1: 使用分隔符来清楚地表明输入的不同部分技巧 2: 要求提供结构化的输出技巧 3: 要求模型检查条件是否得到满足技巧 4: "少许样本…

QML Canvas 元素(绘制文本)

关于 QML Canvas,我们已经学习了如何绘制基本图形、应用样式和颜色、绘制图像等,现在来看一下如何在 Canvas 中绘制文本。 Canvas 提供了两种方式来渲染文本: fillText(text, x, y) 在指定的 (x,y) 位置填充指定的文本 strokeText(text, x, y) 在指定的 (x,y) 位置绘制文本…

基于t分布变异自适应的改进的黏菌算法(TSMA)

目录 一、基于t分布的自适应黏菌优化算法TSAM 1.1 自适应t分布变异 1.2 建立基于t分布的自适应黏菌优化算法TSAM 二、TSMA伪码表示如下&#xff1a; 三、改进对比 黏菌优化算法灵感来自于黏菌的扩张和觅食行为。主要模拟了黏菌在觅食过程中的行为和形态变化&#xff0c;没…

【网络2】MII MDIO

文章目录 1.MII&#xff1a;ISO网络模型中物理层&#xff08;phy&#xff09;和数据链路层&#xff08;mac&#xff09;属于硬件&#xff0c;其余都属于软件kernel2.MDC/MDIO&#xff1a;不仅管phy&#xff0c;只要支持mdio协议都可以管2.1 3.RGMII时序调整&#xff1a;下面波形…

BUUCTF——九连环1

听这个名字就不正常&#xff0c;不会加密九次吧 打开也是一张图片 依旧是存在隐藏文件信息 分离出来后有两个文件&#xff0c;和两个压缩包&#xff0c;但是都需要密码 哦看错了&#xff0c;原来binwalk直接把里面的给分离出来了 所以现在就asd一个文件夹 爆破不出来&#xff0…

为什么调试很重要?gdb调试分析问题

为什么调试很重要&#xff1f; 一、引言二、调试的定义和分类2.1、调试的定义2.2.、调试的分类 三、调试的重要性四、调试的步骤和技巧4.1、定位问题4.2、重现问题4.3、分析问题4.4、解决问题4.5、调试技巧 五、简单的GDB调试示例&#xff1a;六、总结 一、引言 &#x1f4a1; …

【基于Django框架的在线教育平台开发-02】用户注册功能开发

用户注册功能开发 文章目录 用户注册功能开发1 模型层开发2 视图层开发3 配置urls.py4 表单验证5 模板层开发6 效果展示 1 模型层开发 用户数据表如下所示&#xff1a; FieldTypeExtraidintPrime Key & Auto Incrementpasswordvarchar(128)last_logindatetime(6)Allow Nu…

缓存雪崩和缓存穿透的解决方案

缓存雪崩 缓存雪崩是指存储在缓存里面的大量数据&#xff0c;在同一时刻全部过期&#xff0c;大部分流量直接到达了数据库&#xff0c;导致数据库压力增加&#xff0c;造成数据库崩溃的情况。 缓存雪崩的解决方案如下&#xff1a; 每个缓存的key设置不同的过期时间采用多级缓…

STM32单片机(九)USART串口----第四节:USART串口实战练习(串口发送+接收)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

在 K8S 中部署一个应用 下

接着上一篇继续部署应用到 K8S中 之前简单部署的简单集群&#xff0c;三个工作节点是运行在 docker 和 kubelet 的&#xff0c;还有一个是控制节点 ReplicationController &#xff0c; pod 和 service 本次关系 之前有提到 ReplicationController &#xff0c; pod 和 服务…

设计模式之命令模式笔记

设计模式之命令模式笔记 说明Command(命令)目录命令模式示例类图订单类厨师类抽象命令类订单命令类服务员类测试类 说明 记录下学习设计模式-命令模式的写法。JDK使用版本为1.8版本。 Command(命令) 意图:将一个请求封装为一个对象&#xff0c;从而使得可以用不同的请求对客…

STM32单片机(九)USART串口----第二节:USART串口外设

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

STM32单片机(九)USART串口----第三节:USART串口实战练习(串口发送)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

常见面试题之MySQL篇

1.MySQL中&#xff0c;如何定位慢查询? 我们当时做压测的时候有的接口非常的慢&#xff0c;接口的响应时间超过了2秒以上&#xff0c;因为我们当时的系统部署了运维的监控系统Skywalking&#xff0c;在展示的报表中可以看到是哪一个接口比较慢&#xff0c;并且可以分析这个接…

【数据库七】MySQL主从复制与读写分离

MySQL主从复制与读写分离 1.案例概述2.什么是读写分离&#xff1f;3.为什么要读写分离呢&#xff1f;4.什么时候要读写分离&#xff1f;5.主从复制与读写分离6.MySQL主从复制原理6.1 mysql的复制类型 7.主从复制的工作过程7.1 MySQL架构图7.2 口语化工作工程 8.MySQL 读写分离原…

VSCode配置C语言编译环境

一、下载C语言编译器&#xff1a; &#xff08;1&#xff09;下载地址&#xff1a;MinGW-w64 - for 32 and 64 bit Windows - Browse /mingw-w64 at SourceForge.net 下载如下的windows版本&#xff1a; &#xff08;2&#xff09;配置环境变量&#xff1a; 二、安装VSCode …

Linux学习[18]bash学习深入4----命令执行的判断依据---【; , , ||】---用于一次性输入多指令情况

文章目录 前言判断符号 &#xff1b;判断符号 &&与||总结 前言 使用指令的时候&#xff0c;使用完一个指令之后&#xff0c;我想让它接着执行另一个指令&#xff0c;而非等A指令执行完之后再输入B指令。 为了实现这个效果&#xff0c;我查阅了相关资料&#xff0c;这里…

【从零开始学习JAVA | 第十六篇】杂项知识点介绍

目录 前言&#xff1a; 包&#xff1a; final: 权限修饰符&#xff1a; 总结&#xff1a; 前言&#xff1a; 本文不隶属于正文序列&#xff0c;而是对面向对象中的一些常用词进行介绍&#xff0c;方便大家理解记忆&#xff0c;本文将会逐一介绍 什么是包&#xff0c;final…

云服务器部署企业版openGauss

openGauss 企业版安装 教程 1.下载安装包 在华为云上租一台服务器&#xff0c;操作系统选&#xff1a;openEuler 20.03 64bit (64-bit) 获取openGauss Server安装包&#xff0c;企业版&#xff1a;软件包链接 使用xshell连接服务器&#xff0c;准备软硬件安装环境(该装的依…

【软件架构模式】—微内核架构

欢迎回到软件架构模式博客系列。这是本系列的第 4 章&#xff0c;我们将讨论微内核架构模式 概述&#xff1a; 内核模式也被称为插件架构模式。将附加应用程序功能作为插件添加到核心应用程序&#xff0c;以提供可扩展性以及功能分离和隔离。 这种模式由两种类型的架构组件组…