Smb协议实现内网共享目录文件处理及踩坑记录
一、业务场景
公司内网环境,有部分比较古老的业务数据保存在一台windows服务器的共享目录里面。现在需要操作这个windows服务器的共享目录来上传下载删除文件。
二、共享目录
三、查了查资料,操作windows共享目录要通过smb协议。途中遇到一个问题,smb的协议版本问题导致无法连接windows共享目录,最后在GitHub上找到一个日本人对smb封装的依赖。
<dependency><groupId>org.codelibs</groupId><artifactId>jcifs</artifactId><version>2.1.19</version></dependency>
上代码:
上传文件返回链接
/** 共享目录上传* upload* @param file* @return*/@SneakyThrowspublic String upload(MultipartFile file,String custName,Long code) {OutputStream out = null;String filePath = "smb://" + host + path + code + "-" +custName+"/"+file.getOriginalFilename();String path = "smb://" + host + this.path + code + "-" +custName;try {NtlmPasswordAuthenticator npa = new NtlmPasswordAuthenticator(null, userFile, password);CIFSContext context = SingletonContext.getInstance().withCredentials(npa);SmbFile sf = new SmbFile(path, context);if (!sf.exists()){sf.mkdirs();}SmbFile sf1 = new SmbFile(filePath, context);InputStream inputStream = new BufferedInputStream(file.getInputStream());out = new BufferedOutputStream(new SmbFileOutputStream(sf1));byte[] buffer = file.getBytes();//一次性读取所有文件while (inputStream.read(buffer) != -1) {out.write(buffer);}out.flush();}catch (Exception e){try {out.close();}catch (IOException e1){throw new BusinessException("流关闭失败:"+e1.getMessage());}}return this.path + code + "-" +custName+"/"+file.getOriginalFilename();}
下载文件:
/*** 共享目录* @param response*/@SneakyThrowspublic void xiazai(HttpServletResponse response,String addr,String contenType) {String filePath = "smb://"+host+addr;NtlmPasswordAuthenticator npa = new NtlmPasswordAuthenticator(null, userFile, password);CIFSContext context = SingletonContext.getInstance().withCredentials(npa);SmbFile sf = new SmbFile(filePath, context);if (!sf.exists()){throw new BusinessException("文件不存在");}InputStream in = null ;ByteArrayOutputStream out = null ;try {sf.connect(); //尝试连接//创建文件流in = new BufferedInputStream(new SmbFileInputStream(sf));out = new ByteArrayOutputStream((int)sf.length());//读取文件内容byte[] buffer = new byte[4096];int len = 0;while ((len = in.read(buffer, 0, buffer.length)) != - 1) {out.write(buffer, 0, len);}if (StringUtils.isNotEmpty(contenType)){response.setContentType(contenType);}else {response.setContentType("application/force-download");}response.setCharacterEncoding("UTF-8");response.setHeader("Content-Disposition", "no-store");out.writeTo(response.getOutputStream());out.flush();}catch (Exception e) {String msg = "下载远程文件出错:" + e.getLocalizedMessage();System.out.println(msg);}finally {try {if(out != null) {out.close();}if(in != null) {in.close();}}catch (Exception e) {throw new BusinessException(e.getMessage());}}}
删除文件
/*** 共享目录* @param*/@SneakyThrowspublic void remove(String addr) {String filePath = "smb://"+host+addr;NtlmPasswordAuthenticator npa = new NtlmPasswordAuthenticator(null, userFile, password);CIFSContext context = SingletonContext.getInstance().withCredentials(npa);SmbFile sf = new SmbFile(filePath, context);if (!sf.exists()){throw new BusinessException("共享目录或文件不存在:"+addr);}sf.delete();}
创建目录
/*** 共享目录* @param path*/@SneakyThrowspublic void mkdir(String path) {String filePath = "smb://"+host+"/DocLib/"+this.path;NtlmPasswordAuthenticator npa = new NtlmPasswordAuthenticator(null, userFile, password);CIFSContext context = SingletonContext.getInstance().withCredentials(npa);SmbFile sf = new SmbFile(filePath, context);if (!sf.exists()){sf.mkdir();System.out.println("创建成功");}}
查询list
/*** 共享目录* @return*/@SneakyThrowspublic Wrapper list() {String filePath = "smb://"+host+"/DocLib/10";NtlmPasswordAuthenticator npa = new NtlmPasswordAuthenticator(null, userFile, password);CIFSContext context = SingletonContext.getInstance().withCredentials(npa);SmbFile sf = new SmbFile(filePath, context);List<String> list = new ArrayList<>();if (sf != null) {for (int i = 0; i < sf.listFiles().length; i++) {System.out.println(sf.listFiles()[i].getPath());list.add(sf.listFiles()[i].getPath());}}return WrapMapper.ok(list);}