SpringBoot访问windows共享文件

打印 上一主题 下一主题

主题 914|帖子 914|积分 2742

前言

最近有项目需要开发档案打包下载功能,其中包含很多大附件,项目使用minio存储且不在同一台服务器上,为了优化速度决定使用windows共享功能进行文件传输
SMB1.0

集成jcifs类库,主要适用于一些老旧系统,但下载速度比较慢,仅作参考
此类库没有maven引用,官网地址:http://jcifs.samba.org/
注意事项:
设置jcifs.smb.client.dfs.disabled选项开启,可以提高传输速度
使用NtlmPasswordAuthentication认证代替smb协议url携带用户名密码方式,避免特殊字符传递造成认证失败
  1. public static void downloadFile(String ip, String shareFolder, String filePath, String localDir) throws Exception {
  2.         System.setProperty("jcifs.smb.client.dfs.disabled", "true");
  3.         String url = getFileUrl(ip, shareFolder, filePath);
  4.         SmbFile smbFile = new SmbFile(url);
  5.         smbFile.connect();
  6.         FileUtil.initfloderPath(localDir);
  7.         String localFilePath = localDir + "/" + smbFile.getName();
  8.         BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(smbFile));
  9.         FileUtil.writeFile(localFilePath, FileUtil.convertStreamToByte(buf));
  10.     }
  11.     public static void downloadFileByAuth(String ip, String shareFolder, String userName, String password, String filePath, String localDir) throws Exception {
  12.         System.setProperty("jcifs.smb.client.dfs.disabled", "true");
  13.         String url = getFileUrl(ip, shareFolder, filePath);
  14.         NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(ip, userName, password);
  15.         SmbFile smbFile = new SmbFile(url, auth);
  16.         smbFile.connect();
  17.         FileUtil.initfloderPath(localDir);
  18.         String localFilePath = localDir + "/" + smbFile.getName();
  19.         BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(smbFile));
  20.         FileUtil.writeFile(localFilePath, FileUtil.convertStreamToByte(buf));
  21.     }
  22.    
  23.     public static String getFileUrl(String ip, String shareFolder, String filePath) {
  24.         return "smb://" + ip + "/" + shareFolder + "/" + filePath;
  25.     }
复制代码
SMB2.0

集成smbj类库,适用于windows server2012及以上操作系统,默认安装开启无需额外配置
此类库maven引用很久没有发布最新版本,需要下载代码自行编译,github地址:https://github.com/hierynomus/smbj
经测试,500MB文件传输大概比minio协议传输快了4秒左右,小文件传输速度基本保持一致
  1.   public static void downloadFileV2(String ip, String shareFolder, String filePath, String localDir) throws Exception {
  2.         SMBClient client = new SMBClient(SmbConfig.createDefaultConfig());
  3.         Connection conn = client.connect(ip);
  4.         Session session = conn.authenticate(AuthenticationContext.anonymous());
  5.         downLoadSMB2(session, shareFolder, filePath, localDir);
  6.     }
  7.     public static void downloadFileByAuthV2(String ip, String shareFolder, String userName, String password, String filePath, String localDir) throws Exception {
  8.         SMBClient client = new SMBClient(SmbConfig.createDefaultConfig());
  9.         Connection conn = client.connect(ip);
  10.         Session session = conn.authenticate(new AuthenticationContext(userName, password.toCharArray(), ip));
  11.         downLoadSMB2(session, shareFolder, filePath, localDir);
  12.     }
  13.     private static void downLoadSMB2(Session session, String shareFolder, String filePath, String localDir) throws Exception {
  14.         InputStream fis = null;
  15.         FileOutputStream os = null;
  16.         DiskShare diskShare = null;
  17.         try {
  18.             diskShare = (DiskShare) session.connectShare(shareFolder);
  19.             if (!diskShare.fileExists(filePath)) {
  20.                 throw new FileNotFoundException(filePath);
  21.             }
  22.             if (!diskShare.isConnected())
  23.                 diskShare = (DiskShare) session.connectShare(shareFolder);
  24.             com.hierynomus.smbj.share.File file = diskShare.openFile(filePath,
  25.                     EnumSet.of(AccessMask.GENERIC_READ),
  26.                     (Set) null,
  27.                     SMB2ShareAccess.ALL,
  28.                     SMB2CreateDisposition.FILE_OPEN,
  29.                     (Set) null
  30.             );
  31.             fis = file.getInputStream();
  32.             FileUtil.initfloderPath(localDir);
  33.             String[] filePathList = filePath.split("\\/");
  34.             String localFilePath = localDir + "/" + filePathList[filePathList.length - 1];
  35.             os = new FileOutputStream(localFilePath);
  36.             byte[] b = new byte[4096];
  37.             int length;
  38.             while ((length = fis.read(b)) > 0) {
  39.                 os.write(b, 0, length);
  40.             }
  41.         } catch (IOException e) {
  42.             throw e;
  43.         } finally {
  44.             IOUtils.close(os);
  45.             IOUtils.close(fis);
  46.             if (diskShare != null && diskShare.isConnected()) diskShare.close();
  47.         }
  48.     }
复制代码
445端口被禁用解决办法

一般企业/政府项目为了系统安全会禁用445端口,而445端口禁用后文件共享功能无法使用,此时我们需要进行端口转发,即将客户端445端口转发到共享服务器端口A,共享服务器将本地端口A转发到445即可完成共享,具体操作步骤如下,192.168.1.164就是共享文件服务器的内网ip
查看服务器转发规则
  1. netsh interface portproxy show all
复制代码
删除服务器转发规则
  1. netsh interface portproxy reset
复制代码
共享文件服务器

  • 执行CMD代码
  1. netsh interface portproxy add v4tov4 listenport=4455 listenaddress=192.168.1.164 connectport=445 connectaddress=127.0.0.1
  2. netsh interface portproxy add v4tov4 listenport=4455 listenaddress=127.0.0.1 connectport=445 connectaddress=127.0.0.1
复制代码
客户端服务器

  • 关闭Server服务
  • CMD执行代码
  1. netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=445 connectaddress=192.168.1.164 connectport=4455
复制代码

  • 重启系统

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

卖不甜枣

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表