ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Windows 和 Linux 的 远程共享文件夹传输示例

2021-10-22 16:01:25  阅读:208  来源: 互联网

标签:String 示例 Windows share param Linux println SMB out


环境: Win 10 + CentOS 8.1

  1. 下载工程所需要的包,创建java工程,并导入这些包
    包下载

  2. 新建工具类 SmbUtil

package com.wolfe.smb.utils;

import com.hierynomus.msdtyp.AccessMask;
import com.hierynomus.msfscc.FileAttributes;
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;
import com.hierynomus.mssmb2.SMB2CreateDisposition;
import com.hierynomus.mssmb2.SMB2CreateOptions;
import com.hierynomus.mssmb2.SMB2ShareAccess;
import com.hierynomus.mssmb2.SMBApiException;
import com.hierynomus.smbj.SMBClient;
import com.hierynomus.smbj.SmbConfig;
import com.hierynomus.smbj.auth.AuthenticationContext;
import com.hierynomus.smbj.connection.Connection;
import com.hierynomus.smbj.session.Session;
import com.hierynomus.smbj.share.DiskShare;
import com.hierynomus.smbj.share.File;

import java.io.*;
import java.net.SocketTimeoutException;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Create by Wolfe on 2021/10/22
 * Fun: SMB 工具类
 */
public class SmbUtil {
    private static SMBClient client = null;

    // 连接配置
    private static SmbConfig config = SmbConfig.builder().withTimeout(120, TimeUnit.SECONDS)
            .withTimeout(120, TimeUnit.SECONDS) // 超时设置读,写和Transact超时(默认为60秒)
            .withSoTimeout(180, TimeUnit.SECONDS) // Socket超时(默认为0秒)
            .build();

    private static DiskShare getDiskShare(String host, String username, String password, String path) {
        if (client == null) {
            client = new SMBClient(config); // 创建连接客户端
        }

        DiskShare share = null;

        try {
            Connection connection = client.connect(host);// 执行连接

            AuthenticationContext ac = new AuthenticationContext(username, password.toCharArray(), host);
            Session session = connection.authenticate(ac); // 执行权限认证

            share = (DiskShare) session.connectShare(path); // 连接共享文件夹
            return share;
        } catch (SocketTimeoutException e) {
            // host 配置错误 connect timed out
            System.out.println(e.getMessage());
            System.out.println("执行远程连接是失败,请检查远程地址是否正确,或远程共享是否已开启");
        } catch (SMBApiException e) {
            String errMessage = e.getMessage();

            if (errMessage.contains("Could not connect to")) {
                // Could not connect to
                System.out.println(e.getMessage());
                System.out.println("请检查共享目录是否正确");
            }

            if (errMessage.contains("Authentication failed")) {
                // Authentication failed
                System.out.println(e.getMessage());
                System.out.println("请检查连接用户名或密码是否正确");
            }

            if (errMessage.contains("STATUS_OBJECT_NAME_NOT_FOUND")) {
                // STATUS_OBJECT_NAME_NOT_FOUND
                System.out.println(e.getMessage());
                System.out.println("远程目录" + path + "不存在");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return share;
    }

    /**
     * 展示远程目录的文件列表
     *
     * @param host     IP地址
     * @param username 用户名
     * @param password 用户密码
     * @param path     共享目录
     * @param innerDir 内部目录
     */
    public static void listFile(String host, String username, String password, String path, String innerDir) {
        DiskShare share = getDiskShare(host, username, password, path);

        // innerDir 是否存在
        if (!share.folderExists(innerDir)) {
            System.out.println("远程目录" + innerDir + "不存在");
            closeClient(); // 关闭客户端
            return;
        }

        System.out.println("Remote File List:");
        int fileIndex = 0;
        for (FileIdBothDirectoryInformation f : share.list(innerDir, "*")) {
            String fileName = f.getFileName();
            if (!fileName.equals(".") && !fileName.equals("..")) {
                System.out.println(++fileIndex + " : " + f.getFileName());
            }
        }

        closeClient(); // 关闭客户端
    }

    /**
     * 关闭客户端
     */
    private static void closeClient() {
        if (client != null) {
            client.close();
        }
    }

    /**
     * 创建远程目录
     *
     * @param host     IP地址
     * @param username 用户名
     * @param password 用户密码
     * @param path     共享目录
     * @param innerDir 内部目录
     */
    public static void makeDir(String host, String username, String password, String path, String innerDir) {
        DiskShare share = getDiskShare(host, username, password, path);
        createRemoteDir(share, innerDir);
        closeClient(); // 关闭客户端
    }

    /**
     * 创建远程目录
     *
     * @param share
     * @param dirName
     */
    private static void createRemoteDir(DiskShare share, String dirName) {
        // 是否已存在
        if (share.folderExists(dirName)) {
            return;
        }

        // 目录不存在,逐层创建
        String[] fileNameArr = dirName.split("/");
        String tempDirName = ""; // 逐层目录

        for (String fileName : fileNameArr) {
            tempDirName += fileName + "/"; // 下一层目录

            if (share.folderExists(tempDirName)) {
                continue;
            }

            System.out.println("目录: " + tempDirName + " 不存在,即将创建");
            share.mkdir(tempDirName);
        }
    }

    /**
     * 展示远程目录的文件列表
     *
     * @param host     IP地址
     * @param username 用户名
     * @param password 用户密码
     * @param path     共享目录
     */
    public static void listFile(String host, String username, String password, String path) {
        listFile(host, username, password, path, "");
    }

    /**
     * 删除远程文件或文件夹
     *
     * @param host     IP地址
     * @param username 用户名
     * @param password 用户密码
     * @param path     共享目录
     * @param fileName 文件(文件夹)名称
     */
    public static void removeFile(String host, String username, String password, String path, String fileName) {
        DiskShare share = getDiskShare(host, username, password, path); // 连接共享文件夹
        //TODO fileName 是否存在

        // TODO  是目录还是文件 share.rmdir();
        // TODO System.out.println("删除文件夹成功" + fileName);
        share.rm(fileName);
        System.out.println("删除文件" + fileName + "成功.");

        closeClient(); // 关闭客户端
    }

    /**
     * 上传文件到远程
     *
     * @param host          IP地址
     * @param username      用户名
     * @param password      用户密码
     * @param path          共享目录
     * @param innerDir      远程内部文件夹
     * @param localFileName 本地文件
     */
    public static void uploadFile(String host, String username, String password, String path, String innerDir, String localFileName) {
        DiskShare share = getDiskShare(host, username, password, path);

        // 如果目录不存在,逐层创建
        createRemoteDir(share, innerDir);

        try {

            Set<AccessMask> accessMasks = new HashSet<>();
            accessMasks.add(AccessMask.FILE_ADD_FILE);
            Set<FileAttributes> attributes = new HashSet<>();
            attributes.add(FileAttributes.FILE_ATTRIBUTE_NORMAL);
            Set<SMB2ShareAccess> smb2ShareAccesses = new HashSet<>();
            smb2ShareAccesses.add(SMB2ShareAccess.FILE_SHARE_WRITE);
            Set<SMB2CreateOptions> smb2CreateOptions = new HashSet<>();
            smb2CreateOptions.add(SMB2CreateOptions.FILE_RANDOM_ACCESS);

            // 文件名称
            String fileName = innerDir + "/" + localFileName.substring(localFileName.lastIndexOf("/") + 1);

            System.out.println("上传文件: " + fileName);

            File openFile = share.openFile(fileName, accessMasks, attributes, smb2ShareAccesses, SMB2CreateDisposition.FILE_OVERWRITE_IF, smb2CreateOptions);
            OutputStream oStream = openFile.getOutputStream();
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(localFileName));

            byte[] buffer = new byte[1024];
            int len = 0; //Read length
            while ((len = in.read(buffer, 0, buffer.length)) != -1) {
                oStream.write(buffer, 0, len);
            }
            oStream.flush();
            oStream.close();
            System.out.println("文件上传成功");
        } catch (Exception e) {
            System.out.println("文件上传失败");
            e.printStackTrace();
        }
    }


    /**
     * 检查文件夹名称
     *
     * @param dir
     */
    private static String checkDirEnd(String dir) {
        if (!dir.substring(dir.length() - 1).equals("/")) {
            dir += "/";
        }

        return dir;
    }

    /**
     * 创建本地文件夹
     *
     * @param dirName
     */
    private static void createLocalDirIfNotExist(String dirName) {
        java.io.File dir = new java.io.File(dirName);
        if (dir.exists()) {
            return;
        }

        System.out.println("不存在目录" + dir);

        // 不存在,逐层创建
        String[] fileNameArr = dirName.split("/");
        String tempDirName = ""; // 逐层目录

        for (String fileName : fileNameArr) {
            tempDirName += fileName + "/"; // 下一层目录

            java.io.File tempDir = new java.io.File(tempDirName);
            if (tempDir.exists()) {
                continue;
            }

            System.out.println("目录: " + tempDirName + " 不存在,即将创建");
            tempDir.mkdir();//创建文件夹
        }
    }

    /**
     * 下载远程文件
     *
     * @param host       IP地址
     * @param username   用户名
     * @param password   用户密码
     * @param path       共享目录
     * @param remoteFile 远程文件, 可以是具体的文件,可以是匹配的文件
     * @param localDir   本地目标目录
     */
    public static void downloadFile(String host, String username, String password, String path, String remoteFile, String localDir) {
        DiskShare share = getDiskShare(host, username, password, path);

        // 添加文件夹分隔符
        localDir = checkDirEnd(localDir);

        try {

            // 文件夹是否存在,创建本地目录
            createLocalDirIfNotExist(localDir);

            // TODO 远程文件夹
            String remoteDir = "";
            for (FileIdBothDirectoryInformation f : share.list(remoteDir, remoteFile)) {
                String filePath = f.getFileName();

                String dstPath = localDir + f.getFileName();

                FileOutputStream fos = new FileOutputStream(dstPath);
                BufferedOutputStream bos = new BufferedOutputStream(fos);

                if (share.fileExists(filePath)) {
                    System.out.println("正在下载文件: " + f.getFileName());

                    File smbFileRead = share.openFile(filePath, EnumSet.of(AccessMask.GENERIC_READ), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null);
                    InputStream in = smbFileRead.getInputStream();
                    byte[] buffer = new byte[4096];
                    int len = 0;
                    while ((len = in.read(buffer, 0, buffer.length)) != -1) {
                        bos.write(buffer, 0, len);
                    }

                    bos.flush();
                    bos.close();

                    System.out.println("文件下载成功, 保存在 " + dstPath);
                } else {
                    System.out.println("文件 " + filePath + " 不存在");
                }
            }
        } catch (Exception e) {
            System.out.println("文件下载失败");
            e.printStackTrace();
        }
    }

}
  1. 创建测试类
package com.wolfe.smb;

import com.wolfe.smb.utils.SmbUtil;

/**
 * Create by Wolfe  on 2021/10/22
 * Fun: 测试 SMB
 */
public class SmbTest {
    private static final String SMB_REMOTE_HOST = "192.168.137.137"; // 共享服务器IP
    private static final String SMB_USERNAME = "Wolfe"; // SMB 协议用户名
    private static final String SMB_PASSWORD = "Wolfe"; // SMB 协议用户密码
    private static final String SMB_SHARE_PATH = "public"; // 共享目录

    public static void main(String[] args) {
        // 测试,展示远程共享目录下的文件里列表
//        SmbUtil.listFile(SMB_REMOTE_HOST, SMB_USERNAME, SMB_PASSWORD, SMB_SHARE_PATH, "innerDir");

        // 测试,删除远程共享目录的文件(或文件夹)
//        SmbUtil.removeFile(SMB_REMOTE_HOST, SMB_USERNAME, SMB_PASSWORD, SMB_SHARE_PATH, "b.txt");

        // 测试,上传文件到远程目录
        SmbUtil.uploadFile(SMB_REMOTE_HOST, SMB_USERNAME, SMB_PASSWORD, SMB_SHARE_PATH, "tempDir/a/", "c:/test/a.txt");

        // TODO 上传文件夹, 这个比较复杂,先不做了

        // 测试,从远程目录下载文件
//        SmbUtil.downloadFile(SMB_REMOTE_HOST, SMB_USERNAME, SMB_PASSWORD, SMB_SHARE_PATH, "*.pdf", "c:/test/a/b");

        // 创建远程文件夹
//        SmbUtil.makeDir(SMB_REMOTE_HOST, SMB_USERNAME, SMB_PASSWORD, SMB_SHARE_PATH, "a/b");
    }
}

尽情的完吧

标签:String,示例,Windows,share,param,Linux,println,SMB,out
来源: https://blog.csdn.net/weixin_38126537/article/details/120907241

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有