前言

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

SMB1.0

集成jcifs类库,次要实用于一些老旧零碎,但下载速度比较慢,仅作参考

此类库没有maven援用,官网地址:http://jcifs.samba.org/

注意事项:

设置jcifs.smb.client.dfs.disabled选项开启,能够进步传输速度

应用NtlmPasswordAuthentication认证代替smb协定url携带用户名明码形式,防止特殊字符传递造成认证失败

 public static void downloadFile(String ip, String shareFolder, String filePath, String localDir) throws Exception {        System.setProperty("jcifs.smb.client.dfs.disabled", "true");        String url = getFileUrl(ip, shareFolder, filePath);        SmbFile smbFile = new SmbFile(url);        smbFile.connect();        FileUtil.initfloderPath(localDir);        String localFilePath = localDir + "/" + smbFile.getName();        BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(smbFile));        FileUtil.writeFile(localFilePath, FileUtil.convertStreamToByte(buf));    }    public static void downloadFileByAuth(String ip, String shareFolder, String userName, String password, String filePath, String localDir) throws Exception {        System.setProperty("jcifs.smb.client.dfs.disabled", "true");        String url = getFileUrl(ip, shareFolder, filePath);        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(ip, userName, password);        SmbFile smbFile = new SmbFile(url, auth);        smbFile.connect();        FileUtil.initfloderPath(localDir);        String localFilePath = localDir + "/" + smbFile.getName();        BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(smbFile));        FileUtil.writeFile(localFilePath, FileUtil.convertStreamToByte(buf));    }        public static String getFileUrl(String ip, String shareFolder, String filePath) {        return "smb://" + ip + "/" + shareFolder + "/" + filePath;    }

SMB2.0

集成smbj类库,实用于windows server2012及以上操作系统,默认装置开启无需额定配置

此类库maven援用很久没有公布最新版本,须要下载代码自行编译,github地址:https://github.com/hierynomus...

经测试,500MB文件传输大略比minio协定传输快了4秒左右,小文件传输速度根本保持一致

  public static void downloadFileV2(String ip, String shareFolder, String filePath, String localDir) throws Exception {        SMBClient client = new SMBClient(SmbConfig.createDefaultConfig());        Connection conn = client.connect(ip);        Session session = conn.authenticate(AuthenticationContext.anonymous());        downLoadSMB2(session, shareFolder, filePath, localDir);    }    public static void downloadFileByAuthV2(String ip, String shareFolder, String userName, String password, String filePath, String localDir) throws Exception {        SMBClient client = new SMBClient(SmbConfig.createDefaultConfig());        Connection conn = client.connect(ip);        Session session = conn.authenticate(new AuthenticationContext(userName, password.toCharArray(), ip));        downLoadSMB2(session, shareFolder, filePath, localDir);    }    private static void downLoadSMB2(Session session, String shareFolder, String filePath, String localDir) throws Exception {        InputStream fis = null;        FileOutputStream os = null;        DiskShare diskShare = null;        try {            diskShare = (DiskShare) session.connectShare(shareFolder);            if (!diskShare.fileExists(filePath)) {                throw new FileNotFoundException(filePath);            }            if (!diskShare.isConnected())                diskShare = (DiskShare) session.connectShare(shareFolder);            com.hierynomus.smbj.share.File file = diskShare.openFile(filePath,                    EnumSet.of(AccessMask.GENERIC_READ),                    (Set) null,                    SMB2ShareAccess.ALL,                    SMB2CreateDisposition.FILE_OPEN,                    (Set) null            );            fis = file.getInputStream();            FileUtil.initfloderPath(localDir);            String[] filePathList = filePath.split("\\/");            String localFilePath = localDir + "/" + filePathList[filePathList.length - 1];            os = new FileOutputStream(localFilePath);            byte[] b = new byte[4096];            int length;            while ((length = fis.read(b)) > 0) {                os.write(b, 0, length);            }        } catch (IOException e) {            throw e;        } finally {            IOUtils.close(os);            IOUtils.close(fis);            if (diskShare != null && diskShare.isConnected()) diskShare.close();        }    }

445端口被禁用解决办法

个别企业/政府我的项目为了系统安全会禁用445端口,而445端口禁用后文件共享性能无奈应用,此时咱们须要进行端口转发,行将客户端445端口转发到共享服务器端口A,共享服务器将本地端口A转发到445即可实现共享,具体操作步骤如下,192.168.1.164就是共享文件服务器的内网ip

查看服务器转发规定

netsh interface portproxy show all

删除服务器转发规定

netsh interface portproxy reset

共享文件服务器

  • 执行CMD代码
netsh interface portproxy add v4tov4 listenport=4455 listenaddress=192.168.1.164 connectport=445 connectaddress=127.0.0.1netsh interface portproxy add v4tov4 listenport=4455 listenaddress=127.0.0.1 connectport=445 connectaddress=127.0.0.1

客户端服务器

  • 敞开Server服务
  • CMD执行代码
netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=445 connectaddress=192.168.1.164 connectport=4455
  • 重启零碎