Smb协议实现内网共享目录文件处理及踩坑记录
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 */ @SneakyThrows public 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 */ @SneakyThrows public 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 */ @SneakyThrows public 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 */ @SneakyThrows public 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 */ @SneakyThrows public 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); }