前言:最近某项目新增一个需求,需要将原本上传到tomcat 应用服务器上的文件上传到 windos 的共享文件夹,所以综合了网上资料,自己开始了如下尝试。
1、使用smbFile 操作共享文件夹需要用到以下jar 包
org.samba.jcifs
jcifs
1.3.14-kohsuke-1
1、测试连接到smbFile,一般常用的有两种连接方式
第一种就是直接连接到共享文件夹,如下
//smb://xxx:[email protected]/testIndex/
//xxx:xxx是共享机器的用户名密码
String url="smb://wuxw:test@[email protected]/scmqc/";
SmbFile file = new SmbFile(url);
file.connect();
if(file.exists()) {//如果文件存在,获取所有文件进行输出测试
SmbFile[] files = file.listFiles();
for (SmbFile f : files) {
System.out.println(f.getName());
}
}
第二种就是密码中带@特殊符号的,在使用第一种登录方法时会验证失败,因为密码和文件ip区分使用的也是@
这时就可以使用第二种登录方法了,如下
这样就可以将地址与用户信息分离开来,先进行用户信息的认证,就不会验证失败了
// 此处采用优先验证登录用户信息的方法访问
String ip="192.168.43.108";
String url="smb://192.168.43.108/scmqc/";
String name="wuxw\\test";
String password="test@!1234";
NtlmPasswordAuthentication auth =new NtlmPasswordAuthentication(ip, name, password);
SmbFile file = new SmbFile(url,auth);
file.connect();
if(file.exists()){
SmbFile[] files = file.listFiles();
for(SmbFile f : files){
System.out.println(f.getName());
}
}
public void testSmb(){
// 此处采用优先验证登录用户信息的方法访问
String ip="192.168.43.108";
String url="smb://192.168.43.108/scmqc/";
String name="wuxw\\test";
String password="test@!1234";
NtlmPasswordAuthentication auth =new NtlmPasswordAuthentication(ip, name, password);
SmbFile file = new SmbFile(url,auth);
file.connect();
if(file.exists()){
SmbFile[] files = file.listFiles();
for(SmbFile f : files){
System.out.println(f.getName());
}
}
// 下载文件的smb url地址、下载存放地址、用户认证信息
smbFileDowload(url+"test.txt", "D:\\",auth);
// 上传文件的smb url、文件地址、用户认证信息
smbFileUpload(url, "D:\\test.txt", auth);
}
1、上传
//向共享目录上传文件
public void smbFileUpload(String remoteUrl,String localFilePath,NtlmPasswordAuthentication auth) {
InputStream in = null;
OutputStream out = null;
try {
File localFile = new File(localFilePath);
String fileName = localFile.getName();
SmbFile remoteFile = new SmbFile(remoteUrl+"/"+fileName,auth);
in = new BufferedInputStream(new FileInputStream(localFile));
out = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
byte[] buffer = new byte[1024];
while(in.read(buffer)!=-1){
out.write(buffer);
buffer = new byte[1024];
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、下载
// 从共享目录下载文件
public void smbFileDowload(String remoteUrl,String localDir ,NtlmPasswordAuthentication auth) {
InputStream in = null;
OutputStream out = null;
try {
SmbFile remoteFile = new SmbFile(remoteUrl,auth);
if(remoteFile==null){
System.out.println("共享文件不存在");
return;
}
String fileName = remoteFile.getName();
File localFile = new File(localDir+File.separator+fileName);
in = new BufferedInputStream(new SmbFileInputStream(remoteFile));
out = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] buffer = new byte[1024];
while(in.read(buffer)!=-1){
out.write(buffer);
buffer = new byte[1024];
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上的测试在 Windows 本地的 java 环境下运行是完全没有问题的。
首先我这边说明一下为什么会有这一步操作呢,可能因为技术还不到家,所以此点是本人结合项目实际操作加以记录,如果脑子灵活的或者有更好办法的,可以根据第三大点结合自己项目实际就完全不用看这一部分了。
因为在windows操作共享文件夹和 Linux 操作会稍微有点不一致,众所周知,我们写好的代码最终一般都是是要放到 Linux 环境中进行运行的,所以我这里说一下我这边目前将smbFile 放到项目中处理的一个思路。
上传:用户在web 页面上传的文件,先同时存放到tomcat 的应用服务器,然后再从应用服务器放到共享文件夹中,最后再把tomcat 应用服务器中的文件删除。
下载:先将共享文件夹中的文件下载到 tomcat 应用服务器,然后再从 tomcat 应用服务器下载到 用户浏览器,最后再把tomcat 应用服务器中的文件删除。
application.yml 中配置
smb:
name: wuxw\test
password: test@!1234
ip: 192.168.43.108
url: smb://192.168.43.108/scmqc/
filePatch: \\192.168.43.108\scmqc\
#我将这些连接信息放在application.yml 文件中,此处通过注解进行获取
@Value("${smb.name}")
private String name;
@Value("${smb.password}")
private String password;
@Value("${smb.ip}")
private String ip;
@Value("${smb.url}")
private String url;
/**
* 获取用户名密码,登录到共享文件夹
* @return
* @throws Exception
*/
public NtlmPasswordAuthentication connectionSmb() throws Exception {
// 此处使用优先验证登录用户信息的方法访问
NtlmPasswordAuthentication auth =new NtlmPasswordAuthentication(ip, name, password);
SmbFile file = new SmbFile(url,auth);
file.connect();
return auth;
}
1、通过 smbFIle 上传文件
/**
* 向共享目录上传文件
* @param localFilePath 要上传的文件
* @param fileName 要上传的文件名
*/
public void smbUpload(File localFilePath,String fileName) {
InputStream in = null;
OutputStream out = null;
try {
SmbFile remoteFile = new SmbFile(url+fileName,connectionSmb());
in = new BufferedInputStream(new FileInputStream(localFilePath));
out = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
byte[] buffer = new byte[1024];
while(in.read(buffer)!=-1){
out.write(buffer);
buffer = new byte[1024];
}
System.out.println("smb上传成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、 通过 smbFIle 下载文件
/**
* 从共享目录下载文件
* @param fileName 下载的文件名称
* @param localDir 下载文件保存的路径
* @return file
*/
public File smbDownload(String fileName,String localDir ) {
InputStream in = null;
OutputStream out = null;
File localFile = null;
try {
// 拼接smb协议文件下载路径,初始化认证信息
SmbFile remoteFile = new SmbFile(url+fileName,connectionSmb());
if(remoteFile==null){
System.out.println("共享文件不存在");
return null;
}
localFile = new File(localDir+File.separator+fileName);
in = new BufferedInputStream(new SmbFileInputStream(remoteFile));
out = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] buffer = new byte[1024];
while(in.read(buffer)!=-1){
out.write(buffer);
buffer = new byte[1024];
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return localFile;
}
3、外部类中调用 smbFile 上传方法
//localFile 就是已经上传到 tomcat 应用服务器的文件,上传到Tomcat 应用服务器这部分我就不贴出来了
//fileName 就是文件名称
smbFileUtil.smbUpload(localFile,fileName);
//得到要删除的文件进行删除
File deleteFile = new File(localPath);
//如果文件不存在
if (!deleteFile.exists()) {
throw new ZmmaxException("", "文件不存在");
} else {//存在直接删除
deleteFile.delete();
}
4、外部类中调用 smbFile 下载方法
//libFile.getFileName() 就是需要下载的文件名称
//unixFileUpload = /opt/upload/ 就是 tomcat 应用服务器下载地址
file = smbFileUtil.smbDownload(libFile.getFileName(),unixFileUpload);
res.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(libFile.getFileTrueName(), "UTF-8"));
//读取要下载的文件,保存到文件输入流
FileInputStream in = new FileInputStream(file);
OutputStream os = res.getOutputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = in.read(bytes)) > 0) {
os.write(bytes);
}
in.close();
os.close();
//得到要下载的文件,将tomcat服务器上文件删除
File deleteFile = new File(unixFileUpload+libFile.getFileName());
//如果文件不存在
if (!deleteFile.exists()) {
throw new ZmmaxException("", "文件不存在");
} else {//存在直接删除
deleteFile.delete();
}