有同事在外地,他们提供给我的软件包也是在他们本地的,因此开启了windows自带的共享,这样就方便我们取包。由于地域限制,我们访问非常的慢,因此考虑到用Jenkins来触发,下载软件包到我们本地服务器。
先分析下这个需要怎么处理。因为windows共享属于SMB协议,不同的windows系统SMB协议版本不同,目前常见的win7最高支持SMB2,因此对于SMB协议,可以用「JCIFS」库来操作。
- 技术栈:Java
- 知识:JCIFS、SMB
引用JCIFS
创建一个maven工程,然后在pom.xml中添加依赖包。最新的是1.3.18。
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.18</version>
</dependency>
访问共享
访问共享有几种方式,用匿名访问,用户名访问,带域名访问共享,这几种用的不同的方法。我把我自己遇到的坑提出来,希望能帮助到其他人。
- 匿名访问,需要的访问路径加上一个常量ANONYMOUS
import jcifs.smb.SmbFile;
String remoteUrl= "smb//1.1.1.1/smb/package.zip";
smbFile = new SmbFile(remoteUrl, NtlmPasswordAuthentication.ANONYMOUS);
- 用户名访问,直接在路径里面体现用户名和密码,以及域名
import jcifs.smb.SmbFile;
String remoteUrl= "smb//domain;user:passwd@1.1.1.1/smb/package.zip";
SmbFile smbFile = new SmbFile(remoteUrl);
2.1 JCIFS访问共享的时候密码用户名包含了百分号或者特殊符号
这里有一个坑,就是用户名和密码包含了%以及其他的特殊字符,会导致验证失败。所以下面这个问题就可以解决。
3. 先用NtlmPasswordAuthentication,后Get
import jcifs.smb.SmbFile;
import jcifs.smb.NtlmPasswordAuthentication;
String remoteUrl= "smb//1.1.1.1/smb/package.zip";
NtlmPasswordAuthentication ntPassAuth = new
NtlmPasswordAuthentication(domain, user, passwd);
SmbFile smbFile = new SmbFile(remoteUrl, ntPassAuth);
还有一些其他的用法,这里没有用到,可以参考官方API。
获取文件
获取文件用这个SmbFileInputStream,一句话就搞定;
import jcifs.smb.SmbFileInputStream;
in = new BufferedInputStream(new SmbFileInputStream(smbFile));
写入文件
写到本地一样和输入一样的,一句话就可以搞定。
import jcifs.smb.SmbFileInputStream;
out = new BufferedOutputStream(new FileOutputStream(localFile));
Demo
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFileOutputStream;
import jcifs.smb.NtlmPasswordAuthentication;
InputStream in = null;
OutputStream out = null;
long a = new Date().getTime();
try {
// authentication
NtlmPasswordAuthentication ntPassAuth = new
NtlmPasswordAuthentication("ad.xxx.com", "testuser", "pass%word");
// access cifs share
SmbFile smbFile = new SmbFile(remoteUrl, ntPassAuth);
String fileName = smbFile.getName();
int length = smbFile.getContentLength();
// create file as same name
File localFile = new File(localDir + File.separator + fileName);
in = new BufferedInputStream(new SmbFileInputStream(smbFile));
out = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] buffer = new byte[1024 * 1024]; // a buff 1M
int sum = 0;
while ((in.read(buffer)) != -1) {
out.write(buffer);
sum += buffer.length;
System.out.println("Complete: "+sum *100.0/length+"%");
buffer = new byte[1024];
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
long b = new Date().getTime();
int c = (int)((b- a) / 1000);
System.out.println("used time: "+ c +"s");
} catch (IOException e) {
e.printStackTrace();
}
}