2012-11-13 26 views
6

Czy ktoś mógłby mi pomóc skopiować plik z udostępnionego folderu na dysk lokalny? Mój kod to:Jak skopiować plik z udziału smb na dysk lokalny za pomocą jcifs w języku Java?

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

Plik pliku nie jest kopiowany. Otrzymałem komunikat "Nie można połączyć się z serwerem", ale program wyświetla dir.getDate() (oraz nazwę pliku i długość) pliku źródłowego. Więc myślę, że problem z folderem docelowym (C:/SQLRESTORESTAGE /). Mam również dowody tylko do odczytu pliku źródłowego. Czy możesz mi pomóc w korygowaniu kodu lub doradzaniu? Dziękuję Ci.

Odpowiedz

8

może dodawanie uwierzytelniania do drugiego pliku:

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

użyciu SmbFile dest = new SmbFile ("C:/SQLRESTORESTAGE",auth).canWrite wiesz, czy masz uprawnienia do zapisu w katalogu nadrzędnego

7

Po wielu próbach i porażkach jedyna metoda, która pracowała dla mnie wiarygodny było pójść do szkoły i używać FileInputStream i FileOutputStream tak:

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

Wystarczy mała uwaga, lepiej zamknąć strumienie w bloku końcowym. – PomCompot

+0

Aby dodać do komentarza @PomCompot, proponuję również użyć Apache Commons IO i użyć 'IOUtils.closeQuietly (Closeable c)', aby zamknąć swoje strumienie w bloku 'finally'. Cicho ignoruje wszelkie wyjątki wywoływane przez wywoływanie 'close()' w strumieniu, więc bądź świadomy tego zastrzeżenia, chociaż nie znalazłem go osobiście, aby być problemem. – Will

+0

Powyższy kod działa dla mnie Dzięki. –

-2

musisz użyć pliku: protokół

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

Mam go do pracy. Musiałem "stworzyć" plik docelowy przed wykonaniem kopii. spróbuj dodać środkową linię poniżej do oryginalnego fragmentu kodu i sprawdź, czy to działa.

+1

Otrzymuję komunikat "Błąd logowania: nieznana nazwa użytkownika lub złe hasło." wyjątek, mimo że referencje są poprawne. Czy ktoś może mi o tym powiedzieć? Używam tego samego kodu co powyżej – tejas

1

To jest w celu wyjaśnienia. "Błąd logowania: nieznana nazwa użytkownika lub złe hasło." może pokazać się na przykład podczas korzystania z wersji 1.3.18, ale nie w wersji 1.2.25. to prawdopodobnie dlatego, że różne ustawienia Kompatybilność:

  1. jcifs.smb.lmCompatibility = 0 lub 1: Wyślij LM i NTLM 2)
  2. jcifs.smb.lmCompatibility = 2: Wyślij NTLM w obu polach 3)
  3. jcifs.smb.lmCompatibility = 3, 4 lub 5: Wyślij tylko LMv2

Pierwszym sposobem jest użycie go przed NtlmPasswordAuthentication

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

Może rozwiązać ten problem.