Home » Java » How to copy file from smb share to local drive using jcifs in Java?

How to copy file from smb share to local drive using jcifs in Java?

Posted by: admin December 28, 2021 Leave a comment

Questions:

Could anybody help me to copy file from shared folder to local drive? My code is:

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);
      }
}

File file is not copied. I received a message “Failed to connect to server”, but the programm shows dir.getDate() (and file name, and lenght) of source file. So I think the problem with destination folder (C:/SQLRESTORESTAGE/). Also I have proviledges only for reading source file. Could you help me to cirrect the code or advise something? Thank you.

Answers:

maybe adding auth to the second file:

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

using SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE",auth).canWrite
you know if you have write permissions on the parent directory

###

After many trials and failures the only method that worked for me reliably was to go old school and use FileInputStream and FileOutputStream like so:

   `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;
        }
    }`

###

I got it to work. I had to ‘create’ the destination file before doing the copy. try adding the middle line below into your original code-snippet and see if that works.

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

###

This is for clarification.
“Logon failure: unknown user name or bad password.” can show for example when you use 1.3.18 but not in 1.2.25.
it is probably because different compatibility settings:

  1. jcifs.smb.lmCompatibility = 0 or 1: Send LM and NTLM 2)
  2. jcifs.smb.lmCompatibility = 2: Send NTLM in both fields 3)
  3. jcifs.smb.lmCompatibility = 3, 4, or 5: Send just LMv2

First way is to use it before NtlmPasswordAuthentication

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

It can resolve this issue.

###

you must use the file: protocol

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