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

使用C#语言 基于FTP协议进行文件夹上传下载

1. 新增核心功能

文件夹上传 (UploadFolder)
  • 递归遍历本地文件夹结构
  • 自动创建远程目录层级
  • 支持选择是否包含子文件夹
  • 显示上传进度统计
文件夹下载 (DownloadFolder)
  • 获取远程目录结构
  • 本地自动创建对应目录
  • 递归下载所有文件和子目录
  • 区分文件和目录类型

2. 进度报告机制

// 事件驱动的进度报告
public event EventHandler<FtpProgressEventArgs> ProgressChanged;// 进度信息包含:
- 文件名
- 总字节数
- 已传输字节数
- 百分比进度
- 当前操作类型

3. 增强功能详解

FtpFileInfo类

用于存储文件详细信息:

  • Name: 文件/目录名称
  • IsDirectory: 是否为目录
  • Size: 文件大小
  • ModifiedTime: 修改时间
GetDetailedFileList方法

解析Linux FTP服务器的详细列表格式:

drwxr-xr-x 2 user group 4096 Jan 01 12:00 folder
-rw-r--r-- 1 user group 1024 Jan 01 12:00 file.txt
CreateRemoteDirectory方法

支持创建多级目录:

// 自动创建 /path/to/new/folder 整个路径
CreateRemoteDirectory("/path/to/new/folder");

4. 文件夹操作算法

上传文件夹流程
1. 验证本地文件夹存在
2. 创建远程根目录
3. 获取所有文件列表
4. 逐个上传文件,报告进度
5. 递归处理子文件夹(如果需要)
6. 完成统计报告
下载文件夹流程
1. 创建本地目标目录
2. 获取远程文件详细列表
3. 解析区分文件和目录
4. 下载所有文件
5. 递归处理子目录
6. 保持原始目录结构

5. Linux兼容性优化

路径处理
// Windows路径转换为Linux格式
string remoteDir = Path.GetDirectoryName(remoteFileName).Replace('\\', '/');// 路径拼接使用正斜杠
string remoteFilePath = string.Format("{0}/{1}", remoteFolderPath.TrimEnd('/'), file.Name);
权限解析

支持解析Linux文件权限格式:

  • d 开头表示目录
  • - 开头表示文件
  • 权限位:rwxrwxrwx

6. 错误处理增强

目录创建容错
// 550错误表示目录已存在,不作为错误处理
if (ex.Message.Contains("550"))
{return true;  // 目录已存在,继续执行
}
递归操作保护
  • 跳过 ... 特殊目录
  • 防止无限递归

7. 性能优化

可配置缓冲区
ftpClient.BufferSize = 4096;  // 根据网络状况调整
连接管理
  • 每个操作独立连接
  • 自动释放资源
  • 避免连接超时

8. 使用场景示例

批量备份场景
// 备份整个项目到Linux服务器
ftpClient.UploadFolder(@"D:\Projects\WebApp","/backup/2024-01-01/WebApp",true
);
同步下载场景
// 从Linux服务器同步日志文件夹
ftpClient.DownloadFolder("/var/log/myapp",@"C:\Logs\ServerLogs",true
);
进度监控场景
ftpClient.ProgressChanged += (sender, e) => {progressBar.Value = e.ProgressPercentage;labelStatus.Text = $"{e.CurrentOperation}: {e.FileName}";labelProgress.Text = $"{e.TransferredBytes}/{e.TotalBytes}";
};

9. Linux服务器配置建议

# vsftpd配置文件示例 (/etc/vsftpd.conf)
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
listen=YES
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES# 支持UTF-8文件名
utf8_filesystem=YES

10. 最佳实践

大文件处理
  • 增大缓冲区到8KB或16KB
  • 考虑实现断点续传
  • 添加重试机制
并发操作
  • 使用线程池处理多文件
  • 限制并发连接数
  • 实现队列管理
安全建议
  • 使用FTPS或SFTP
  • 定期更换密码
  • 限制FTP用户权限
  • 监控传输日志

11. 扩展功能建议

  1. 断点续传:记录传输位置,支持中断恢复
  2. 压缩传输:传输前压缩,减少带宽使用
  3. 增量同步:比较文件修改时间,只传输变化的文件
  4. 多线程传输:并行传输多个文件提高效率
  5. 传输队列:管理批量传输任务
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;namespace FtpFileTransfer
{/// <summary>/// FTP传输进度事件参数/// </summary>public class FtpProgressEventArgs : EventArgs{public string FileName { get; set; }public long TotalBytes { get; set; }public long TransferredBytes { get; set; }public int ProgressPercentage { get; set; }public string CurrentOperation { get; set; }}/// <summary>/// FTP文件传输类,支持文件和文件夹的上传下载/// </summary>public class FtpClient{private string ftpServerIP;private string ftpUserID;private string ftpPassword;private int ftpPort;private int bufferSize = 2048;// 进度报告事件public event EventHandler<FtpProgressEventArgs> ProgressChanged;/// <summary>/// 构造函数/// </summary>/// <param name="serverIP">FTP服务器IP地址</param>/// <param name="userID">用户名</param>/// <param name="password">密码</param>/// <param name="port">端口号(默认21)</param>public FtpClient(string serverIP, string userID, string password, int port = 21){this.ftpServerIP = serverIP;this.ftpUserID = userID;this.ftpPassword = password;this.ftpPort = port;}/// <summary>/// 设置缓冲区大小/// </summary>public int BufferSize{get { return bufferSize; }set { bufferSize = value > 0 ? value : 2048; }}/// <summary>/// 触发进度变化事件/// </summary>protected virtual void OnProgressChanged(FtpProgressEventArgs e){if (ProgressChanged != null)ProgressChanged(this, e);}/// <summary>/// 上传文件到FTP服务器(带进度报告)/// </summary>public bool UploadFile(string localFilePath, string remoteFileName){FileInfo fileInfo = new FileInfo(localFilePath);string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);FtpWebRequest request = null;FileStream fs = null;Stream requestStream = null;try{// 确保远程目录存在string remoteDir = Path.GetDirectoryName(remoteFileName).Replace('\\', '/');if (!string.IsNullOrEmpty(remoteDir)){CreateRemoteDirectory(remoteDir);}// 创建FTP请求request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.KeepAlive = false;request.Method = WebRequestMethods.Ftp.UploadFile;request.UseBinary = true;request.ContentLength = fileInfo.Length;request.Timeout = 30000;byte[] buff = new byte[bufferSize];int contentLen;long totalUploaded = 0;// 打开本地文件流fs = fileInfo.OpenRead();// 获取FTP请求流requestStream = request.GetRequestStream();// 读取文件并写入FTP流contentLen = fs.Read(buff, 0, bufferSize);while (contentLen != 0){requestStream.Write(buff, 0, contentLen);totalUploaded += contentLen;// 报告进度OnProgressChanged(new FtpProgressEventArgs{FileName = fileInfo.Name,TotalBytes = fileInfo.Length,TransferredBytes = totalUploaded,ProgressPercentage = (int)((totalUploaded * 100) / fileInfo.Length),CurrentOperation = "上传文件"});contentLen = fs.Read(buff, 0, bufferSize);}Console.WriteLine("文件 {0} 上传成功", fileInfo.Name);return true;}catch (Exception ex){Console.WriteLine("上传文件时发生错误: " + ex.Message);return false;}finally{if (requestStream != null)requestStream.Close();if (fs != null)fs.Close();if (request != null)request.Abort();}}/// <summary>/// 上传整个文件夹到FTP服务器/// </summary>/// <param name="localFolderPath">本地文件夹路径</param>/// <param name="remoteFolderPath">远程文件夹路径</param>/// <param name="includeSubfolders">是否包含子文件夹</param>/// <returns>上传是否成功</returns>public bool UploadFolder(string localFolderPath, string remoteFolderPath, bool includeSubfolders = true){try{if (!Directory.Exists(localFolderPath)){Console.WriteLine("本地文件夹不存在: " + localFolderPath);return false;}// 获取所有文件和文件夹DirectoryInfo dirInfo = new DirectoryInfo(localFolderPath);// 创建远程根目录if (!string.IsNullOrEmpty(remoteFolderPath)){CreateRemoteDirectory(remoteFolderPath);}// 上传所有文件FileInfo[] files = dirInfo.GetFiles();int uploadedCount = 0;int totalFiles = files.Length;Console.WriteLine("开始上传文件夹,共 {0} 个文件", totalFiles);foreach (FileInfo file in files){string remoteFilePath = string.Format("{0}/{1}", remoteFolderPath.TrimEnd('/'), file.Name);if (UploadFile(file.FullName, remoteFilePath)){uploadedCount++;Console.WriteLine("进度: {0}/{1}", uploadedCount, totalFiles);}}// 递归处理子文件夹if (includeSubfolders){DirectoryInfo[] subDirs = dirInfo.GetDirectories();foreach (DirectoryInfo subDir in subDirs){string remoteSubPath = string.Format("{0}/{1}", remoteFolderPath.TrimEnd('/'), subDir.Name);UploadFolder(subDir.FullName, remoteSubPath, true);}}Console.WriteLine("文件夹上传完成: {0}", localFolderPath);return true;}catch (Exception ex){Console.WriteLine("上传文件夹时发生错误: " + ex.Message);return false;}}/// <summary>/// 从FTP服务器下载文件(带进度报告)/// </summary>public bool DownloadFile(string remoteFileName, string localFilePath){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);FtpWebRequest request = null;FtpWebResponse response = null;Stream responseStream = null;FileStream outputStream = null;try{// 获取远程文件大小long fileSize = GetFileSize(remoteFileName);// 创建FTP请求request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Method = WebRequestMethods.Ftp.DownloadFile;request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.UseBinary = true;request.KeepAlive = false;request.Timeout = 30000;// 获取响应response = (FtpWebResponse)request.GetResponse();responseStream = response.GetResponseStream();// 创建本地目录string directoryPath = Path.GetDirectoryName(localFilePath);if (!Directory.Exists(directoryPath)){Directory.CreateDirectory(directoryPath);}outputStream = new FileStream(localFilePath, FileMode.Create);byte[] buffer = new byte[bufferSize];long totalDownloaded = 0;int readCount = responseStream.Read(buffer, 0, buffer.Length);while (readCount > 0){outputStream.Write(buffer, 0, readCount);totalDownloaded += readCount;// 报告进度if (fileSize > 0){OnProgressChanged(new FtpProgressEventArgs{FileName = Path.GetFileName(localFilePath),TotalBytes = fileSize,TransferredBytes = totalDownloaded,ProgressPercentage = (int)((totalDownloaded * 100) / fileSize),CurrentOperation = "下载文件"});}readCount = responseStream.Read(buffer, 0, buffer.Length);}Console.WriteLine("文件下载成功: {0}", localFilePath);return true;}catch (Exception ex){Console.WriteLine("下载文件时发生错误: " + ex.Message);return false;}finally{if (outputStream != null)outputStream.Close();if (responseStream != null)responseStream.Close();if (response != null)response.Close();if (request != null)request.Abort();}}/// <summary>/// 下载整个文件夹从FTP服务器/// </summary>/// <param name="remoteFolderPath">远程文件夹路径</param>/// <param name="localFolderPath">本地文件夹路径</param>/// <param name="includeSubfolders">是否包含子文件夹</param>/// <returns>下载是否成功</returns>public bool DownloadFolder(string remoteFolderPath, string localFolderPath, bool includeSubfolders = true){try{// 创建本地目录if (!Directory.Exists(localFolderPath)){Directory.CreateDirectory(localFolderPath);}// 获取远程文件列表List<FtpFileInfo> remoteFiles = GetDetailedFileList(remoteFolderPath);int downloadedCount = 0;int totalFiles = 0;// 统计文件数量foreach (var item in remoteFiles){if (!item.IsDirectory)totalFiles++;}Console.WriteLine("开始下载文件夹,共 {0} 个文件", totalFiles);// 下载文件和处理子目录foreach (var item in remoteFiles){if (item.IsDirectory){// 处理子目录if (includeSubfolders && item.Name != "." && item.Name != ".."){string remoteSubPath = string.Format("{0}/{1}", remoteFolderPath.TrimEnd('/'), item.Name);string localSubPath = Path.Combine(localFolderPath, item.Name);DownloadFolder(remoteSubPath, localSubPath, true);}}else{// 下载文件string remoteFilePath = string.Format("{0}/{1}", remoteFolderPath.TrimEnd('/'), item.Name);string localFilePath = Path.Combine(localFolderPath, item.Name);if (DownloadFile(remoteFilePath, localFilePath)){downloadedCount++;Console.WriteLine("进度: {0}/{1}", downloadedCount, totalFiles);}}}Console.WriteLine("文件夹下载完成: {0}", remoteFolderPath);return true;}catch (Exception ex){Console.WriteLine("下载文件夹时发生错误: " + ex.Message);return false;}}/// <summary>/// 获取详细的文件列表(包含文件/目录标识)/// </summary>public List<FtpFileInfo> GetDetailedFileList(string remotePath){List<FtpFileInfo> fileList = new List<FtpFileInfo>();string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remotePath);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);string line = reader.ReadLine();while (line != null){FtpFileInfo fileInfo = ParseFileInfo(line);if (fileInfo != null){fileList.Add(fileInfo);}line = reader.ReadLine();}reader.Close();response.Close();}catch (Exception ex){Console.WriteLine("获取详细文件列表时发生错误: " + ex.Message);}return fileList;}/// <summary>/// 解析FTP列表详细信息(兼容Linux格式)/// </summary>private FtpFileInfo ParseFileInfo(string line){try{FtpFileInfo fileInfo = new FtpFileInfo();// Linux FTP服务器格式: drwxr-xr-x 2 user group 4096 Jan 01 12:00 filenamestring[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);if (parts.Length >= 9){// 判断是否为目录fileInfo.IsDirectory = parts[0].StartsWith("d");// 获取文件名(可能包含空格)fileInfo.Name = string.Join(" ", parts, 8, parts.Length - 8);// 获取文件大小long size;if (long.TryParse(parts[4], out size)){fileInfo.Size = size;}}else if (parts.Length > 0){// 简单格式,只有文件名fileInfo.Name = line.Trim();fileInfo.IsDirectory = false;}return fileInfo;}catch{return null;}}/// <summary>/// 创建远程目录(支持多级目录)/// </summary>public bool CreateRemoteDirectory(string remotePath){try{string[] dirs = remotePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);string currentPath = "";foreach (string dir in dirs){currentPath += "/" + dir;if (!RemoteDirectoryExists(currentPath)){CreateDirectory(currentPath);}}return true;}catch (Exception ex){Console.WriteLine("创建远程目录失败: " + ex.Message);return false;}}/// <summary>/// 检查远程目录是否存在/// </summary>private bool RemoteDirectoryExists(string remotePath){try{string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remotePath);FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.ListDirectory;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();response.Close();return true;}catch{return false;}}/// <summary>/// 获取文件大小/// </summary>public long GetFileSize(string remoteFileName){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.GetFileSize;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();long size = response.ContentLength;response.Close();return size;}catch{return -1;}}/// <summary>/// 获取FTP服务器上的文件列表(简单)/// </summary>public string[] GetFileList(string remotePath){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remotePath);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.ListDirectory;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);string line = reader.ReadLine();StringBuilder result = new StringBuilder();while (line != null){result.Append(line);result.Append("\n");line = reader.ReadLine();}reader.Close();response.Close();if (result.Length > 0){result.Remove(result.ToString().LastIndexOf('\n'), 1);return result.ToString().Split('\n');}else{return new string[] { };}}catch (Exception ex){Console.WriteLine("获取文件列表时发生错误: " + ex.Message);return new string[] { };}}/// <summary>/// 删除FTP服务器上的文件/// </summary>public bool DeleteFile(string remoteFileName){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.DeleteFile;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();response.Close();Console.WriteLine("文件 {0} 删除成功", remoteFileName);return true;}catch (Exception ex){Console.WriteLine("删除文件时发生错误: " + ex.Message);return false;}}/// <summary>/// 删除远程文件夹(包含所有内容)/// </summary>public bool DeleteFolder(string remoteFolderPath){try{// 获取文件夹内容List<FtpFileInfo> items = GetDetailedFileList(remoteFolderPath);// 先删除所有文件和子文件夹foreach (var item in items){if (item.Name == "." || item.Name == "..")continue;string itemPath = string.Format("{0}/{1}", remoteFolderPath.TrimEnd('/'), item.Name);if (item.IsDirectory){// 递归删除子文件夹DeleteFolder(itemPath);}else{// 删除文件DeleteFile(itemPath);}}// 删除空文件夹RemoveDirectory(remoteFolderPath);Console.WriteLine("文件夹删除成功: {0}", remoteFolderPath);return true;}catch (Exception ex){Console.WriteLine("删除文件夹时发生错误: " + ex.Message);return false;}}/// <summary>/// 删除空目录/// </summary>private bool RemoveDirectory(string directoryName){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, directoryName);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.RemoveDirectory;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();response.Close();return true;}catch (Exception ex){Console.WriteLine("删除目录时发生错误: " + ex.Message);return false;}}/// <summary>/// 创建FTP服务器上的目录/// </summary>public bool CreateDirectory(string directoryName){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, directoryName);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.MakeDirectory;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();response.Close();Console.WriteLine("目录 {0} 创建成功", directoryName);return true;}catch (Exception ex){// 目录可能已存在,这不算错误if (ex.Message.Contains("550")){return true;}Console.WriteLine("创建目录时发生错误: " + ex.Message);return false;}}/// <summary>/// 检查文件是否存在/// </summary>public bool FileExists(string remoteFileName){string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);try{FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);request.Method = WebRequestMethods.Ftp.GetFileSize;request.KeepAlive = false;FtpWebResponse response = (FtpWebResponse)request.GetResponse();response.Close();return true;}catch{return false;}}}/// <summary>/// FTP文件信息类/// </summary>public class FtpFileInfo{public string Name { get; set; }public bool IsDirectory { get; set; }public long Size { get; set; }public DateTime ModifiedTime { get; set; }}/// <summary>/// 使用示例/// </summary>class Program{static void Main(string[] args){// 创建FTP客户端实例FtpClient ftpClient = new FtpClient("192.168.1.100",  // Linux服务器IP"username",        // FTP用户名"password",        // FTP密码21                 // FTP端口);// 设置缓冲区大小(可选)ftpClient.BufferSize = 4096;  // 4KB// 订阅进度事件ftpClient.ProgressChanged += FtpClient_ProgressChanged;Console.WriteLine("========== 文件操作示例 ==========");// 上传单个文件bool uploadResult = ftpClient.UploadFile(@"C:\local\test.txt","/remote/path/test.txt");// 下载单个文件bool downloadResult = ftpClient.DownloadFile("/remote/path/test.txt",@"C:\download\test.txt");Console.WriteLine("\n========== 文件夹操作示例 ==========");// 上传整个文件夹(包含子文件夹)bool uploadFolderResult = ftpClient.UploadFolder(@"C:\local\myproject",          // 本地文件夹"/remote/projects/myproject",    // 远程文件夹true                             // 包含子文件夹);// 下载整个文件夹(包含子文件夹)bool downloadFolderResult = ftpClient.DownloadFolder("/remote/projects/myproject",    // 远程文件夹@"C:\download\myproject",        // 本地文件夹true                             // 包含子文件夹);Console.WriteLine("\n========== 文件管理操作 ==========");// 获取详细文件列表List<FtpFileInfo> files = ftpClient.GetDetailedFileList("/remote/path/");foreach (var file in files){Console.WriteLine("{0} - {1} - {2} bytes", file.IsDirectory ? "[目录]" : "[文件]", file.Name, file.Size);}// 创建多级目录ftpClient.CreateRemoteDirectory("/remote/new/multi/level/dir");// 删除文件夹及其内容ftpClient.DeleteFolder("/remote/old/folder");// 获取文件大小long fileSize = ftpClient.GetFileSize("/remote/bigfile.zip");Console.WriteLine("文件大小: {0} bytes", fileSize);Console.WriteLine("\n按任意键退出...");Console.ReadLine();}/// <summary>/// 进度变化事件处理/// </summary>static void FtpClient_ProgressChanged(object sender, FtpProgressEventArgs e){Console.SetCursorPosition(0, Console.CursorTop);Console.Write("{0}: {1} - {2:F2} MB / {3:F2} MB ({4}%)     ", e.CurrentOperation,e.FileName,e.TransferredBytes / 1048576.0,  // 转换为MBe.TotalBytes / 1048576.0,        // 转换为MBe.ProgressPercentage);}}
}
http://www.xdnf.cn/news/19522.html

相关文章:

  • ansible知识点总结1
  • C/C++ Linux系统编程:进程通讯完全指南,管道通讯、共享内存以及消息队列
  • Linux之Docker虚拟化技术(三)
  • nacos微服务介绍及环境搭建
  • Oracle 查询有哪些用户 提示用户名密码无效
  • AI 入门指南:从 “听不懂人话” 到 “比你懂你”,人工智能到底是个啥?
  • shell编程 函数、数组与正则表达式
  • 网络与信息安全有哪些岗位:(13)安全服务工程师 / 顾问
  • pip不是内部或外部命令的问题怎么解决?
  • 基于.NET Framework 4.0的FTP文件传输类
  • 【云存储桶安全】怎么满足业务需求,又最大程度上满足信息安全要求呢?
  • 构建深度学习音频识别模型:从数据预处理到性能评估
  • 【K8s】整体认识K8s之监控与升级/ETCD的备份和恢复/kustomization/CRD
  • wpf之样式
  • PAT 1089 Insert or Merge
  • UBUNTU之Onvif开源服务器onvif_srvd:1、编译
  • 如何使用VMware创建一台Ubuntu机器
  • Shell脚本实用技巧集锦:从时间判断到系统监控
  • 【数据可视化-104】安徽省2025年上半年GDP数据可视化分析:用Python和Pyecharts打造炫酷大屏
  • HTTP/2 多路复用
  • 网络流量分析——熟悉Wireshark
  • 时序数据库国产的有哪些?
  • ​​--flush-logs 的作用:刷新 MySQL 的日志文件(主要是二进制日志 binlog)​
  • 解析简历重难点与面试回答要点
  • 【开题答辩全过程】以 健身爱好者饮食管理小程序为例,包含答辩的问题和答案
  • LeetCode82删除排序链表中的重复元素 II
  • 力扣hot100 | 堆 | 215. 数组中的第K个最大元素、347. 前 K 个高频元素、128. 最长连续序列
  • 《架构师手记:SpringCloud整合Nacos实战·一》
  • Transformer的并行计算与长序列处理瓶颈总结
  • 可编辑115页PPT | 某纸制品制造企业数字化转型战略规划项目建议书