当前位置: 首页 > java >正文

【FileZilla】上传下载时文件夹的处理

 先看一个下载动作的调用轨迹(下载一个或多个文件或文件夹):

// Function bool CQueueView::TryStartNextTransfer() in QueueView.cpp
while (newFileItem && newFileItem->Download() && newFileItem->GetType() == QueueItemType::Folder) {CLocalPath localPath(newFileItem->GetLocalPath());localPath.AddSegment(newFileItem->GetLocalFile());wxFileName::Mkdir(localPath.GetPath(), 0777, wxPATH_MKDIR_FULL);const std::vector<CState*> *pStates = CContextManager::Get()->GetAllStates();for (auto & state : *pStates) {state->RefreshLocalFile(localPath.GetPath());}if (RemoveItem(newFileItem, true)) {// Server got deleted. Unfortunately we have to start over nowif (m_serverList.empty()) {return false;}return true;}newFileItem = currentServerItem->GetIdleChild(m_activeMode == 1, wantedDirection);
}

这段代码从队列中拿出一个项,如果是文件夹的话,就在本地创建文件夹并删除这个项(下载语境)。那么问题来了,这个文件夹里的文件们是什么时候放进队列里的呢?

void local_recursive_operation::thread_entry()
{{fz::scoped_lock l(mutex_);auto filters = m_filters.first;while (!recursion_roots_.empty()) {listing d;bool recurse{true};{auto& root = recursion_roots_.front();if (root.m_dirsToVisit.empty()) {recursion_roots_.pop_front();continue;}auto const& dir = root.m_dirsToVisit.front();d.localPath = dir.localPath;d.remotePath = dir.remotePath;recurse = dir.recurse;root.m_dirsToVisit.pop_front();}// Do the slow part without holding mutexl.unlock();bool sentPartial = false;fz::local_filesys fs;fz::native_string localPath = fz::to_native(d.localPath.GetPath());if (fs.begin_find_files(localPath)) {listing::entry entry;bool isLink{};fz::native_string name;fz::local_filesys::type t{};while (fs.get_next_file(name, isLink, t, &entry.size, &entry.time, &entry.attributes)) {if (isLink && m_ignoreLinks) {continue;}entry.name = fz::to_wstring(name);if (!filter_manager::FilenameFiltered(filters, entry.name, d.localPath.GetPath(), t == fz::local_filesys::dir, entry.size, entry.attributes, entry.time)) {if (t == fz::local_filesys::dir) {d.dirs.emplace_back(std::move(entry));}else {d.files.emplace_back(std::move(entry));}// If having queued 5k items, hand off to main thread.if (d.files.size() + d.dirs.size() >= 5000) {sentPartial = true;listing next;next.localPath = d.localPath;next.remotePath = d.remotePath;l.lock();// Check for cancellationif (recursion_roots_.empty()) {l.unlock();break;}EnqueueEnumeratedListing(l, std::move(d), recurse);l.unlock();d = next;}}}}l.lock();// Check for cancellationif (recursion_roots_.empty()) {break;}if (!sentPartial || !d.files.empty() || !d.dirs.empty()) {EnqueueEnumeratedListing(l, std::move(d), recurse);}}listing d;m_listedDirectories.emplace_back(std::move(d));}on_listed_directory();
}

在上传时,会由do_start_recursive_operation()启动一个执行local_recursive_operation::thread_entry()的线程。这个线程不停从嵌套根recursion_roots_里,拿出来目录里需要访问的目录root.m_dirsToVisit,然后在目录下找文件,找到文件就存文件到d.files.emplace_back(std::move(entry)),找到目录就存目录到d.dirs.emplace_back(std::move(entry))。找到到超过5000个文件,或者扫描结束,则通过EnqueueEnumeratedListing(l, std::move(d), recurse)和on_listed_directory(),把存入的目录入队列root.add_dir_to_visit(localSub, remoteSub)、把存入的文件m_pQueue->QueueFiles(!m_immediate, site_, d)入系统的文件下载处理的队列。这就处理完啦!

void local_recursive_operation::EnqueueEnumeratedListing(fz::scoped_lock& l, listing&& d, bool recurse)
{if (recursion_roots_.empty()) {return;}auto& root = recursion_roots_.front();if (recurse) {// Queue for recursionfor (auto const& entry : d.dirs) {local_recursion_root::new_dir dir;CLocalPath localSub = d.localPath;localSub.AddSegment(entry.name);CServerPath remoteSub = d.remotePath;if (!remoteSub.empty()) {if (m_operationMode == recursive_transfer) {// Non-flatten caseremoteSub.AddSegment(entry.name);}}root.add_dir_to_visit(localSub, remoteSub); // !!!!!!}}m_listedDirectories.emplace_back(std::move(d));// Hand off to GUI threadif (m_listedDirectories.size() == 1) {l.unlock();on_listed_directory();l.lock();}
}
void CLocalRecursiveOperation::on_listed_directory() {CallAfter(&CLocalRecursiveOperation::OnListedDirectory);
}void CLocalRecursiveOperation::OnListedDirectory()
{if (m_operationMode == recursive_none) {return;}bool const queue = m_operationMode == recursive_transfer || m_operationMode == recursive_transfer_flatten;listing d;bool stop = false;int64_t processed = 0;while (processed < 5000) {{fz::scoped_lock l(mutex_);if (m_listedDirectories.empty()) {break;}d = std::move(m_listedDirectories.front());m_listedDirectories.pop_front();}if (d.localPath.empty()) {stop = true;}else {if (queue) {m_pQueue->QueueFiles(!m_immediate, site_, d); // !!!!!!}++m_processedDirectories;processed += d.files.size();state_.NotifyHandlers(STATECHANGE_LOCAL_RECURSION_LISTING, std::wstring(), &d);}}if (queue) {m_pQueue->QueueFile_Finish(m_immediate);}m_processedFiles += processed;if (stop) {StopRecursiveOperation();}else if (processed) {state_.NotifyHandlers(STATECHANGE_LOCAL_RECURSION_STATUS);if (processed >= 5000) {CallAfter(&CLocalRecursiveOperation::OnListedDirectory);}}
}

http://www.xdnf.cn/news/8046.html

相关文章:

  • VR光伏车棚虚拟仿真系统:开启绿色能源新视界​
  • openai-whisper-asr-webservice接入dify
  • “智”斗秸秆焚烧,考拉悠然以科技之力筑牢生态安全防线
  • 解决自签名证书HTTPS告警:强制使用SHA-256算法生成证书
  • openCV1-2 图像的直方图相关
  • 微服务架构中的 RabbitMQ:异步通信与服务解耦(二)
  • SQLMesh 宏操作符详解:提升 SQL 查询的灵活性与效率
  • Spring Boot与Eventuate Tram整合:构建可靠的事件驱动型分布式事务
  • 高等数学-积分
  • ElasticSearch操作
  • HarmonyOS 鸿蒙应用开发基础:父组件调用子组件方法的几种实现方案对比
  • HarmonyOS 鸿蒙应用开发基础:@Watch装饰器详解及与@Monitor装饰器对比分析
  • HarmonyOS实战:高德地图自定义定位图标展示
  • Redis 5.0.10 集群部署实战(3 主 3 从,三台服务器)
  • 深度学习模型部署:使用Flask将图像分类(5类)模型部署在服务器上,然后在本地GUI调用。(全网模型部署项目步骤详解:从模型训练到部署再到调用)
  • RAGFlow知识检索原理解析:混合检索架构与工程实践
  • Dify大语言模型应用开发环境搭建:打造个性化本地LLM应用开发工作台
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的管理与运营策略研究
  • 格雷希尔快速封堵接头,解决新能源汽车的气密性检测和三电系统的综合测试
  • java 基础知识巩固
  • 深度解析:Spark、Hive 与 Presto 的融合应用之道
  • SpringBoot Day_03
  • Docker 与微服务架构:从单体应用到容器化微服务的迁移实践
  • 谷歌medgemma-27b-text-it医疗大模型论文速读:多语言大型语言模型医学问答基准测试MedExpQA
  • 基于STM32F4的cubemx关于RTC配置说明
  • Docker架构详解
  • Win 系统 conda 如何配置镜像源
  • 【二刷力扣】【力扣热题100】今天的题目是:两数之和
  • Spring核心原理:动态数据源切换的企业级解决方案
  • springboot03