С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 05.07.2011
Сообщений: 204

Скачивание по FTP целой папки

04.08.2025, 15:42. Показов 1284. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!
попытаюсь подробно изложить проблему.
В программе реализовано копирование с/на удаленный сервер(УС) файлов по FTP
методом перетаскивания. все работает нормально.
при копировании с ПК на УС курсор меняется, а при отпускании в (DragDrop)
начинается процесс копирования, все ок.
при обратном методе(с УС на ПК) (DragDrop) не возникает, а процесс копирования происходит в (ItemDrag)
при том, что файлы копируются во временную папку.
а на шаге (DoDragDrop(obj, DragDropEffects.Copy) уже из временной переносится в паку назначения.

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

выдернул часть кода для понимания, он старый, зато все наглядно.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void mlvTKPFile_ItemDrag(object sender, ItemDragEventArgs e) {
  string[] files = new string[mlvFile.SelectedItems.Count];
  foreach (ListViewItem selFiles in mlvFile.SelectedItems) {
    files[i++] = currentfolder_tkp + "/" + selFiles.Text;
  }
  if (files != null) {
     string filename = Path.GetFileName(files[0]);                                
     // Создание объекта для перетаскивания, который "понимает" оболочка
     if (File.Exists(tempfolder + "\\" + filename)) {
         var obj = new DataObject(DataFormats.FileDrop, new string[] { tempfolder + "\\" + filename });
          DoDragDrop(obj, DragDropEffects.Copy); // копирование из временной папки в папку назначения.
     }
   }
}
как можно начать копирование только после отпускания кнопки мыши?
кто-то сталкивался с этим?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.08.2025, 15:42
Ответы с готовыми решениями:

Скачивание целой папки
как можно реализовать скачивание папки(в этой папке много других папок и файлов) с сайта или ФТП...

Скачивание папки с FTP - сервера по актуальной дате
Здравствуйте. Возможно ли реализовать скачку с фтп папки в которой находятся файлы, папок много, а...

Скачивание папки с FTP - сервера по актуальной дате (2)
Продолжение темы https://www.cyberforum.ru/csharp-net/thread2329455.html var mStr =...

12
 Аватар для Andrey-MSK
3319 / 2206 / 387
Регистрация: 14.08.2018
Сообщений: 7,416
Записей в блоге: 4
04.08.2025, 16:09
Цитата Сообщение от sonmax Посмотреть сообщение
то система как бы "подвисает"
Используйте асинхронные методы (async/await, Task). Тогда и подвисать не будет, и отменить задачу сможете, и прогресс рисовать можно.
0
0 / 0 / 0
Регистрация: 05.07.2011
Сообщений: 204
04.08.2025, 17:33  [ТС]
спасибо, но я вот не пойму, а как это поможет?
"подвисает" - потому что идет теневое скачивание, без моего ведома.
если бы оно начиналось после отпускания ЛКМ, то проблемы бы и не было.
может есть примерчик?
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
05.08.2025, 02:00
Цитата Сообщение от sonmax Посмотреть сообщение
но я вот не пойму, а как это поможет?
Форма зависает на действии DoDragDrop, т.к. оно не асинхронное. Т.е. пока не скопируются все ваши 100500 ГБ, приложение ведёт себя как мёртвое. Чтобы такого не было, есть технология async-await. Ну или банально вынести в отдельный Thread.
0
0 / 0 / 0
Регистрация: 05.07.2011
Сообщений: 204
05.08.2025, 12:43  [ТС]
Да нет же, вы неправильно поняли.
зависает уже до DoDragDrop, т.е. идет теневое скачивание во временную папку.
а уже на DoDragDrop из временной в целевую, тут все быстро.
0
 Аватар для Andrey-MSK
3319 / 2206 / 387
Регистрация: 14.08.2018
Сообщений: 7,416
Записей в блоге: 4
05.08.2025, 12:52
Цитата Сообщение от sonmax Посмотреть сообщение
Да нет же, вы неправильно поняли.
Правильно мы поняли. Во время копирования метод работает в основном потоке приложения. Так как метод синхронный, вот он и вешает приложение. Сделайте копирование асинхронным и всё будет нормально.
0
0 / 0 / 0
Регистрация: 05.07.2011
Сообщений: 204
05.08.2025, 13:49  [ТС]
как асинхронный метод может запретить копирование с УС в процессе перетаскивания?
вы предлагаете правильно, но это не решит проблему теневого копирования.
может курсор и будет правильно отображаться, но мне желательно сделать
копирование именно при отпускании ЛКМ.
как это организовано при копировании с ПК на УС.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3398 / 2720 / 574
Регистрация: 04.09.2018
Сообщений: 8,542
Записей в блоге: 3
05.08.2025, 15:08
sonmax, убрать DoDragDrop из события mlvTKPFile_ItemDrag. Копировать (начинать) после события отпускания ЛКМ над целевым контролом.
0
0 / 0 / 0
Регистрация: 05.07.2011
Сообщений: 204
05.08.2025, 15:57  [ТС]
еще раз,
1. выбираю файл(папку) в listview ("Технические данные ...")
2. нажимаю ЛКМ и "тащу" на рабочий стол.
3. как только начинаю двигать, срабатывает ItemDrag и начинается теневое копирование во временную папку.
во время этого, визуальной информации о том пользователь что-то перетаскивает нет.
4. как только заканчивается теневое копирование, сразу визуальная информация становится доступной.
5. при отпускании ЛКМ, например, над "рабочим столом" срабатывает DoDragDrop.
т.е. файл(папка) из временной переносится на "рабочий стол"

под "визуальной информацией" я понимаю это смена иконки с default на copy и обратно

проблема именно в п3
Миниатюры
Скачивание по FTP целой папки  
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3398 / 2720 / 574
Регистрация: 04.09.2018
Сообщений: 8,542
Записей в блоге: 3
05.08.2025, 16:15
sonmax,
1. зачем копировать во "временную " папку?
2. само копирование начинается при событии ItemDrag - это прописано у тебя в коде. Мышку дернул - началось копирование.
Если это не то поведение, которое нужно - убирай его от сюда и меняй логику на нужную..

Добавлено через 12 минут
Логика должна быть примерно такая:
- ухватились на элемент, начали "тащить". В этот момент запоминается путь того, что "ухватили".
- тащим до элемента, на котором разрешено событие Drop.
- только при "бросании" элемента на этом контроле должно начаться копирование.

Потому как:
- мы можем случайно схватить не ту папку;
- в процессе перетаскивания можем передумать копировать;
поэтому НЕ бросание в целевой контрол не должно приводить ни к какому копированию..
0
 Аватар для Andrey-MSK
3319 / 2206 / 387
Регистрация: 14.08.2018
Сообщений: 7,416
Записей в блоге: 4
05.08.2025, 16:23
Цитата Сообщение от sonmax Посмотреть сообщение
копирование именно при отпускании ЛКМ.
как это организовано при копировании с ПК на УС.
Ну покажите как это сделано. Зачем ссылаться на то, что вы не показываете...

И после отпускания ЛКМ пишите код самого копирования, обёрнутый в Task
C#
1
await Task.Run(() => { // тут ваш код копирования данных });
тогда приложение не зависнет, а будет обрабатывать всё остальное. Если в коде копирования сделаете просчёт прогресса операции, из него можно будет вывести прогресс на форму, вызовом делегатов, что бы не получить ошибку работы потоков, и показывать сколько сделано, сколько осталось и т.д.
Вот пример асинхронного копирования файла с прогрессом и т.д. Это для WPF, но мысль, думаю, будет понятна.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Метод обработки нажатия кнопки
private async void BtnDownload_Click(object sender, RoutedEventArgs e)
{
    string updatePath = App.Current.Configuration["AppSettings:UpdatesDebugURI"];
    string source = Path.Combine(updatePath, _updateInfo.FileName);
    string destination = Path.Combine(_userTempFolder, _updateInfo.FileName);
 
    try
    {
        btnDownload.IsEnabled = false;
 
        using (_cts = new CancellationTokenSource())
        {
            await CopyFile(source, destination, new Progress<int>(v => pgDownloadProgress.Value = v), _cts.Token);
        }
 
        string message = "Загрузка обновления завершена.\n\r\n\rНажмите кнопку \"Обновить\" для начала операции обновления.\n\r\n\rДождитесь запуска мастера установки!";
 
        btnDownload.Visibility = Visibility.Collapsed;
        btnOK.Visibility = Visibility.Visible;
 
        MessageBox.Show(message, "Обновление", MessageBoxButton.OK, MessageBoxImage.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}
 
// Метод копирования файла из файловой системы
private static async Task CopyFile(string source, string destination, IProgress<int> status, CancellationToken token)
{
    try
    {
        FileInfo sourceFile = new FileInfo(source);
        long totalBytes = sourceFile.Length;
        long bytesCopied = 0;
 
        using (FileStream sourceStream = sourceFile.OpenRead())
        {
            using (FileStream destStream = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                byte[] buffer = new byte[8192];
                int bytesRead;
                int progress = 0;
                int oldProgress;
 
                while ((bytesRead = await sourceStream.ReadAsync(buffer, token)) > 0)
                {
                    await destStream.WriteAsync(buffer.AsMemory(0, bytesRead), token);
 
                    bytesCopied += bytesRead;
                    oldProgress = progress;
                    progress = (int)(bytesCopied * 100 / totalBytes);
 
                    if (oldProgress != progress)
                        status?.Report(progress);
                }
            }
        }
    }
    catch (OperationCanceledException)
    {
        return;
    }
    catch (Exception ex)
    {
        throw new ApplicationException(ex.Message, ex);
    }
}
0
0 / 0 / 0
Регистрация: 05.07.2011
Сообщений: 204
05.08.2025, 17:46  [ТС]
наверное надо извиниться.
задавая вопрос я ориентировался на устаревший код.
и в итоге проблема не столько в самом копировании,
сколько в событии окончания перетаскивания.
вот более актуальный код, дальше только видео снимать.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 private void mlvTKPFile_ItemDrag(object sender, ItemDragEventArgs e) {
   foreach (ListViewItem selFiles in mlvTKPFile.SelectedItems) {
     files[i++] = currentfolder_tkp + "/" + selFiles.Text;
   }
   if (files == null) return;
   string filename = Path.GetFileName(files[0]);  // только имя под ним и сохраним
    // копирование ftp 
   ftp.downloadFile(currentfolder_tkp + "/" + filename, tempfolder + "\\" + filename); // скачиваю в tmp
    // Создание объекта для перетаскивания, который "понимает" оболочка
   if (File.Exists(tempfolder + "\\" + filename)) {
      var obj = new DataObject(DataFormats.FileDrop, new string[] { tempfolder + "\\" + filename });
      DoDragDrop(obj, DragDropEffects.Copy);
   }
}
проблема на шаге 8. т.е. я запускаю копирование во временную папку сразу при начале перемещения.
это неправильно, и хоть как то обойти проблему добавил File.Exists.
но только так я могу получить папку назначения когда отпускаю ЛКМ.
DoDragDrop - позволяет получить этот путь и скопировать туда.
самый правильный вариант отлавливать mouse_up и только после этого копировать,
но mlvTKPFile_MouseUp не срабатывает, т.к. ЛКМ я отпускаю на "рабочем столе"
по этой же причине не работает mlvTKPFile_DragDrop
и по какому тут событию отрабатывать. непонятно
0
06.08.2025, 00:17

Не по теме:

Цитата Сообщение от sonmax Посмотреть сообщение
самый правильный вариант отлавливать mouse_up и только после этого копировать
самый правильный вариант разнести логику так, чтобы в у вас был бизнес-класс отвечающий за действия и ничего не сведующий о WinForms, а всякие Control_Event(object sender, EvetArgs e) дергали исключительно один метод "сделать то-то". В этом случае вопросов "почему зависает" не будет априори, т.к. вынести в Task|Thread можно весь вызываемый метод и не парится (почти).

Делать это в срочном порядке конечно не стоит, но если планируете существенный рефакторинг приложения -- явно напрашивается навести порядок в таком коде.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.08.2025, 00:17
Помогаю со студенческими работами здесь

Скачивание файла с FTP
Добрый день форумчане. Обращаюсь к вам за помощью. Мне требуется скачать файл с FTP сервера. На...

Подключение к FTP и скачивание HTML файл
У меня возник вопрос, как можно подключится к FTP имея хост, логин и пароль. И выкачать от туда...

Создать используя Task аснхронное скачивание с ftp
Здравствуйте . Подскажите пожалуйста как переделать синхронный метод в асинхронный ? private...

Скачивание файла с ftp сервера
Привет! Решил попробовать написать систему обновления для своей программы. Есть вот такая идея:...

Скачивание файла с FTP
Доброго времени суток, помогите пожалуйста, мне нужно что бы при открытия 2 формы(авторизаций)...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru