本地到服务器文件拷贝正常,服务器到本地拷贝遇登录失败问题求助
问题描述
尝试将PDF文件从SMB服务器拷贝到本地文件夹时,持续遇到以下错误:
Logon failure: unknown user name or bad password.
对应的实现函数如下:
public void copyPasteFileFromNetwerkDriveToLocal(String source, String destFileUrl, String destFileName) { InputStream in = null; OutputStream out = null; try { NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain","user","password"); String remoteDocUrl = "smb:"+source; //The shared directory to store pictures SmbFile remoteDocUrlFile = new SmbFile(remoteDocUrl, auth); remoteDocUrlFile.connect(); //Try to connect if (remoteDocUrlFile.exists()) { String remoteDocUrlAndName = "smb:"+source; SmbFile remoteDocFile = new SmbFile(remoteDocUrlAndName, auth); remoteDocFile.connect(); //Try to connect File localFile = new File(destFileUrl+destFileName); in = new BufferedInputStream(new SmbFileInputStream(remoteDocFile)); out = new BufferedOutputStream(new FileOutputStream(localFile)); byte[] buffer = new byte[4096]; int len = 0; //Read length while ((len = in.read(buffer, 0, buffer.length)) != -1) { out.write(buffer, 0, len); } out.flush(); //The refresh buffer output stream } } catch (Exception e) { String msg = "The error occurred: " + e.getLocalizedMessage(); System.out.println(msg); } finally { try { if(out != null) { out.close(); } if(in != null) { in.close(); } } catch (Exception e) {} } }
但使用相同用户名和密码,从本地到服务器的文件拷贝功能却可以正常运行,对应的函数如下:
public void copyPasteFileFromLocalToNetwerkDrive(String source, String destFileUrl, String destFileName) { InputStream in = null; OutputStream out = null; try { //Get a picture File localFile = new File(source); NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain","user","password"); String remoteDocUrl = "smb:"+destFileUrl; //The shared directory to store pictures SmbFile remoteDocUrlFile = new SmbFile(remoteDocUrl, auth); remoteDocUrlFile.connect(); //Try to connect if (!remoteDocUrlFile.exists()) { //maak alle directories remoteDocUrlFile.mkdirs(); } String remoteDocUrlAndName = "smb:"+destFileUrl+destFileName; SmbFile remoteDocFile = new SmbFile(remoteDocUrlAndName, auth); remoteDocFile.connect(); //Try to connect in = new BufferedInputStream(new FileInputStream(localFile)); out = new BufferedOutputStream(new SmbFileOutputStream(remoteDocFile)); byte[] buffer = new byte[4096]; int len = 0; //Read length while ((len = in.read(buffer, 0, buffer.length)) != -1) { out.write(buffer, 0, len); } out.flush(); //The refresh buffer output stream } catch (Exception e) { String msg = "The error occurred: " + e.getLocalizedMessage(); System.out.println(msg); } finally { try { if(out != null) { out.close(); } if(in != null) { in.close(); } } catch (Exception e) {} } }
请问哪里操作有误?
问题分析与解决
对比两个函数,核心问题出在从服务器到本地的函数中,source参数的路径拼接逻辑错误:
- 在
copyPasteFileFromNetwerkDriveToLocal函数里,remoteDocUrl和remoteDocUrlAndName都直接拼接了smb:+source,如果source本身已经包含smb://前缀,就会生成smb:smb://xxx的非法路径,导致认证失败。而正常工作的copyPasteFileFromLocalToNetwerkDrive函数中,destFileUrl是不带smb:前缀的服务器共享目录路径,所以拼接逻辑是合法的。
另外还有两个冗余问题:
- 重复创建了两个指向同一路径的
SmbFile对象,完全可以复用第一个对象,避免重复连接。 - 手动调用
connect()是多余的,SmbFile在执行exists()、getInputStream()等操作时会自动建立连接。
修复后的函数示例:
public void copyPasteFileFromNetwerkDriveToLocal(String source, String destFileUrl, String destFileName) { InputStream in = null; OutputStream out = null; try { NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain","user","password"); // 确保source是合法的SMB路径:如果不带smb前缀则添加,否则直接使用 String remoteFilePath = source.startsWith("smb:") ? source : "smb:" + source; SmbFile remoteDocFile = new SmbFile(remoteFilePath, auth); if (remoteDocFile.exists()) { // 用File构造函数拼接本地路径,避免分隔符问题 File localFile = new File(destFileUrl, destFileName); in = new BufferedInputStream(new SmbFileInputStream(remoteDocFile)); out = new BufferedOutputStream(new FileOutputStream(localFile)); byte[] buffer = new byte[4096]; int len; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } out.flush(); } } catch (Exception e) { System.out.println("错误发生: " + e.getLocalizedMessage()); } finally { try { if(out != null) out.close(); if(in != null) in.close(); } catch (Exception e) {} } }
额外注意事项:
- 拼接本地路径时,优先使用
new File(destFileUrl, destFileName)替代字符串拼接,避免因不同系统路径分隔符差异导致的错误。 - 检查
source参数的传入值,确认是否已经包含smb:前缀,这是导致认证报错的最直接原因。
内容的提问来源于Stack Exchange,提问作者Laurens Wolf
相关产品推荐
相关产品推荐

