如何使用 Java 中的 jcifs 将文件从 smb 共享复制到本地驱动器?

Posted

技术标签:

【中文标题】如何使用 Java 中的 jcifs 将文件从 smb 共享复制到本地驱动器?【英文标题】:How to copy file from smb share to local drive using jcifs in Java? 【发布时间】:2012-11-01 18:55:44 【问题描述】:

谁能帮我将文件从共享文件夹复制到本地驱动器?我的代码是:

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFileOutputStream;;


public class smb 

      /**
      * @param args
      * @throws IOException
       */
      public static void main(String[] args) throws IOException 
            // TODO Auto-generated method stub


          String urlToBackUpFile = "smb://ip/backup$/test.txt"; 
          System.out.println("smb folder of source file" + urlToBackUpFile);
          NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(null, "login", "pass");


            SmbFile dir = new SmbFile(urlToBackUpFile, auth);
            System.out.println(dir.getDate());
            SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE/v2.bak");
            dir.copyTo(dest);
      

文件文件未被复制。我收到一条消息“无法连接到服务器”,但程序显示源文件的 dir.getDate()(和文件名和长度)。所以我认为目标文件夹(C:/SQLRESTORETAGE/)的问题。此外,我只有读取源文件的权限。你能帮我解决代码或建议吗?谢谢。

【问题讨论】:

【参考方案1】:

也许将身份验证添加到第二个文件:

SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE/v2.bak",**auth**);

使用SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE",auth).canWrite 你知道你是否对父目录有写权限

【讨论】:

【参考方案2】:

在多次尝试和失败之后,唯一对我有效的方法是回到老学校,像这样使用 FileInputStream 和 FileOutputStream:

   `SmbFile[] files = getSMBListOfFiles(sb, logger, domain, userName, password, sourcePath, sourcePattern);

    if (files == null)
        return false;
    output(sb, logger, "      Source file count: " + files.length);
    String destFilename;
    FileOutputStream fileOutputStream;
    InputStream fileInputStream;
    byte[] buf;
    int len;
    for (SmbFile smbFile: files) 
        destFilename = destinationPath + smbFile.getName();
        output(sb, logger, "         copying " + smbFile.getName());
        try 
            fileOutputStream = new FileOutputStream(destFilename);
            fileInputStream = smbFile.getInputStream();
            buf = new byte[16 * 1024 * 1024];
            while ((len = fileInputStream.read(buf)) > 0) 
                fileOutputStream.write(buf, 0, len);
            
            fileInputStream.close();
            fileOutputStream.close();
         catch (SmbException e) 
            OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, SMP issue: " + e.getMessage(), e);
            e.printStackTrace();
            return false;
         catch (FileNotFoundException e) 
            OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, file not found: " + e.getMessage(), e);
            e.printStackTrace();
            return false;
         catch (IOException e) 
            OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, IO problem: " + e.getMessage(), e);
            e.printStackTrace();
            return false;
        
    `

【讨论】:

请注意,最好在 finally 块中关闭您的流。 要添加到 @PomCompot 的评论中,我还建议使用 Apache Commons IO 并使用 IOUtils.closeQuietly(Closeable c) 关闭 finally 块中的流。它会悄悄地忽略通过在流上调用 close() 引发的任何异常,因此请注意该警告,尽管我个人还没有发现它是一个问题。【参考方案3】:

我让它工作了。在进行复制之前,我必须“创建”目标文件。尝试将下面的中间行添加到您的原始代码-sn-p 中,看看是否可行。

SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE/v2.bak");
dest.createNewFile();
dir.copyTo(dest);

【讨论】:

我收到“登录失败:未知用户名或密码错误”。尽管凭据正确,但异常。有人可以告诉我吗?我使用与上面相同的代码【参考方案4】:

这是为了澄清。 “登录失败:未知用户名或密码错误。”例如,当您使用 1.3.18 而不是 1.2.25 时可以显示。 这可能是因为不同的兼容性设置:

    jcifs.smb.lmCompatibility = 0 或 1:发送 LM 和 NTLM 2) jcifs.smb.lmCompatibility = 2:在两个字段中发送 NTLM 3) jcifs.smb.lmCompatibility = 3、4 或 5:仅发送 LMv2

第一种方法是在 NtlmPasswordAuthentication 之前使用它

jcifs.Config.setProperty( "jcifs.smb.lmCompatibility", "3");

它可以解决这个问题。

【讨论】:

【参考方案5】:

你必须使用文件:协议

SmbFile dest = new SmbFile ("file:" + "C:/SQLRESTORESTAGE/v2.bak");

【讨论】:

以上是关于如何使用 Java 中的 jcifs 将文件从 smb 共享复制到本地驱动器?的主要内容,如果未能解决你的问题,请参考以下文章

性能:使用 JCIF 将文件复制到 Windows 网络非常慢

JCIFS SmbException

如何使用 JCIFS 移动(而不是复制)文件?

jcifs.smb.SmbAuthException:登录失败:未知用户名或密码错误。

使用最后一个 smb jcifs-ng jar 复制文件

使用 Java 和 Samba JCIFS 访问文件