Многопоточный FTP скачать - PullRequest
3 голосов
/ 29 сентября 2011

Я пытаюсь обработать определенный каталог FTP, который содержит несколько каталогов, и в свою очередь эти каталоги имеют произвольное количество файлов.Итак, что я пытаюсь сделать, это иметь 1 поток для каждой из подкаталогов, и каждый поток, связанный с соответствующим подкаталогом, вот что я придумал:

private void fetchFilesFromFTP() {

    try {
        client.connect("ftp.ncbi.nih.gov");
        client.login("anonymous", "anonymous");

        client.changeWorkingDirectory("genomes/Fungi");

        FTPFile dirs[] = client.listDirectories();
        dirsToDl.addAndGet(dirs.length); 

        for (final FTPFile ftpFile : dirs) {
            exec.execute(new Runnable() {
                //process each FTP directory in a new thread
                @Override
                public void run() {
                    processFTPdir(ftpFile.getName());
                }
            });
        }
    } catch (SocketException ex) {
        Logger.getLogger(FungiProcessor.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(FungiProcessor.class.getName()).log(Level.SEVERE, null, ex);
    } 
}

private void processFTPdir(String dir) {

    File f = new File(destination + File.separator + dir);
    if (!f.mkdirs()) {
        System.out.println("Error creating dir for " + dir);
        return;
    }

    FTPFile files[];
    try {
        //we are already in the correct directory
        files = client.listFiles(dir, new FTPFileFilter() {

            @Override
            public boolean accept(FTPFile ftpf) {
                return ftpf.getName().endsWith(".gbk");
            }
        });

        for (FTPFile fTPFile : files) {
            FileOutputStream fout =  new FileOutputStream(destination + File.separator + dir + File.separator + fTPFile.getName());
            if (client.retrieveFile(dir + "/" + fTPFile.getName(), fout)) {

                System.out.println("successfully downloaded");
                fout.flush();
                fout.close();
            }
            System.out.println(client.getReplyString());
        }
    } catch (IOException ex) {
        Logger.getLogger(FungiProcessor.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        if(dirsToDl.decrementAndGet() == 0) latch.countDown();
    }
}

Последовательная версиякод работает - я вижу файлы, заканчивающиеся на .gbk, которые фактически загружаются, тогда как в многопоточной версии создаются только соответствующие подкаталоги, но файлы не загружаются.Я даже не получаю никаких ошибок.Возможно ли, что FTP не поддерживает загрузку нескольких файлов одновременно?

Ответы [ 2 ]

3 голосов
/ 29 сентября 2011

Лучший способ - подключить к серверу один шаг с собственным клиентом и создать список путей к файлам, которые вы хотите загрузить. Затем вы запускаете несколько потоков, каждый со своим клиентом, который берет первый из списка и начинает загрузку файла.

Количество одновременных подключений, которые вы можете иметь к одному ftp-серверу, ограничено настройками этого сервера.

1 голос
/ 29 сентября 2011

Я очень сомневаюсь, что это будет работать с несколькими потоками. Все потоки будут использовать один и тот же клиент (и, следовательно, один и тот же командный канал), и FTP не предоставляет способ мультиплексирования, необходимый для его работы. (Ответы на команды двух потоков выглядят практически одинаково; FTP не может сказать «это ответ на команду 1».)

Вам нужно было бы, чтобы каждый поток захватил блокировку перед отправкой команды и разблокировал только после получения ответа ... принудительное выполнение по одной команде за раз и сериализация всего настолько, что вы потеряете все преимущества многопоточности в любом случае. Единственный способ обойти это - использовать клиента для каждого потока, но тогда вы в конечном итоге столкнетесь с ограничениями на соединения для каждого пользователя (которые, как правило, довольно строги).

В целом, это звучит как работа для одного потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...