Как скопировать файл из общего ресурса SMB на локальный диск, а не в домен с JCIFS

Я пытаюсь скопировать некоторые удаленные файлы на локальный диск, на Java, используя JCIFS. Удаленная машина находится внутри домена. Локальный компьютер не в домене.

Следующий код работает, но он действительно медленный (2 минуты для 700Kb ... и у меня много Mb ...):

SmbFile remoteFile = new SmbFile("smb://...")
OutputStream os = new FileOutputStream("/path/to/local/file");
InputStream is = remoteFile.getInputStream();
int ch;
while ((ch = is.read()) != -1) {
    os.write(ch);
}
os.close();
is.close();

Я думаю, что я мог бы использовать SmbFile.copyTo (), но я не знаю, как получить доступ к локальному файлу. Если я напишу следующее, я получаю ошибку подключения:

localfile = new SmbFile("file:///path/to/localfile")

This question is related to How to copy file from smb share to local drive using jcifs in Java?

4
nl ja de

3 ответы

Вам просто нужно сделать больший буфер:

   SmbFile remoteFile = new SmbFile("smb://...")
   OutputStream os = new FileOutputStream("/path/to/local/file");
   InputStream is = remoteFile.getInputStream();

                  int bufferSize = 5096;

                  byte[] b = new byte[bufferSize];
                  int noOfBytes = 0;
                         while( (noOfBytes = is.read(b)) != -1 )
                  {
                      os.write(b, 0, noOfBytes);
                  }
                    os.close();
                    is.close();

Вот несколько тестов, которые я сделал с файлом 23 Мб, используя упомянутый код.

bufferSize = 1024 Истекшее время: 10.9587606066 sec

bufferSize = 4096 Истекшее время: 5.6239662951 сек.

bufferSize = 5096 Истекшее время: 5.0798761245 sec

bufferSize = 5096 Истекшее время: 4.879439883 сек.

bufferSize = 10240 Истекшее время: 4.0192989201 sec

bufferSize = 50240 Истекшее время: 3.8876541543 sec

bufferSize = 100240 Истекшее время: 3.742167582 сек.

5
добавлено
Слишком много времени для создания InputStream и копирования в файл назначения. У меня был файл 1 КБ, и для завершения этой операции потребовалось более 1 мин. Есть ли способ сделать это быстро ????
добавлено автор Jaikrat, источник

Объект SmbFile не может быть создан кроме с допустимым URL smb . См. Резюме конструктора в http://jcifs.samba.org/src/docs/api/ , а также обсуждение URL-адресов SmbFile вверху.

URL-адреса SmbFile имеют следующий синтаксис:   СМБ://[[[домен]; имя пользователя [: пароль] @] сервер [: порт]/[[доля/[реж /] файл]]]? [[PARAM = значение [param2 = значение2 [...] ]]

Итак, если вы действительно хотите избежать использования потока ввода и использовать copyTo (), вам придется иметь общий SMB-ресурс на вашей локальной машине, на который вы можете указать jCIFS.

Если ваш локальный компьютер является машиной Windows, есть некоторые общие домены, к которым вы могли бы получить доступ, например C $.

Итак, вы можете сделать что-то вроде:

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain", "username", "password") //or whatever authentication works on your local machine.
SmbFile myFile = new SmbFile("smb://localhost/C\$/path/to/localfile", auth)

Затем вы можете использовать remoteFile.copyTo (myFile) .

Если вы не находитесь на хосте Windows, вам нужно будет установить Samba и настроить общий ресурс Samba для подключения к вашей локальной машине ... снова, если вы абсолютно склонны избегать использования inputStreams.

4
добавлено
Что такое remoteFile ??
добавлено автор Jaikrat, источник
О да, спасибо. Я реализовал это и свою работу. Но его принятие tooooo много времени, чтобы сделать InputStream и скопировать. Есть ли способ сделать это быстро?
добавлено автор Jaikrat, источник
Примечательно, что nagualjj указывает, что вы также можете использовать формат «C:/path/to/file», но я не имел успеха в этом. stackoverflow.com/questions/13359164
добавлено автор jonnybot, источник
Из исходного вопроса remoteFile - это SmbFile, который OP хочет скопировать в другое место (в этом случае myFile ).
добавлено автор jonnybot, источник

В качестве альтернативы отвечу @maxmimko вы также можете использовать библиотеку IO Apache Commons и использовать IOUtils для обработки копирования для вас:

NtlmPasswordAuthentication creds = new NtlmPasswordAuthentication("domain", "user", "password");
SmbFile remoteFile = new SmbFile("smb://REMOTEHOST/SHARE/path/to/file", creds);
try (
    InputStream is = remoteFile.getInputStream();
    OutputStream os = new FileOutputStream("/path/to/local/file");
) {
    long bytesCopied = IOUtils.copyLarge(is, os);
} catch (IOException e) {
   //handle exception here; log it?
}
// streams are automatically closed by try-with-resources block

Существует также IOUtils.copyLarge (InputStream is, OutputStream os, byte [] buffer) , если вы хотите контролировать размер буфера, но я нашел значения по умолчанию, используемые IOUtils , чтобы быть относительно хорошим по всем направлениям.

4
добавлено