项目背景:
我们系统涉及多个站点,最初文件写入本地磁盘,后来使用文件服务器,但是有部分客户认为smb的高位端口445 135-139开放 共享文件的方式不足够安全。
由于文件写入的入口较多,考虑使用文件同步工具进行两台机器进行文件同步比如(微力同步)
1、原始SMB 共享文件夹方式
因为使用的c# 代码直接把附件上传到本地磁盘目录,所以在后来采用文件服务器之后,通过iis 创建虚拟目录,虚拟目录映射了文件服务器的共享文件夹(SMB 的 共享方式,c#写文件的代码不需要更改)。
//smb的方式,本质上只要配置好权限,和写入本地服务器没有区别
static void Main() { string smbPath = @"\\192.168.1.100\shared_folder\test.txt"; // SMB 共享路径 string content = "Hello, SMB!"; try { File.WriteAllText(smbPath, content); Console.WriteLine("文件写入成功!"); } catch (Exception ex) { Console.WriteLine($"写入失败: {ex.Message}"); } }
2、使用 WebDAV 访问和写入 HTTP 共享文件夹
WebDAV(Web Distributed Authoring and Versioning)是一种基于 HTTP/HTTPS 的文件共享协议,允许客户端(如 IIS)远程访问和操作远程文件系统。
步骤 1:确保目标服务器支持 WebDAV
- 如果目标服务器(如
http://example.com/shared
)已经提供了 WebDAV 服务(如 Windows IIS 的 WebDAV 功能、Nextcloud、OwnCloud 等),可以直接访问。 - 如果没有,需要先在目标服务器上启用 WebDAV(例如在 Windows IIS 上配置 WebDAV 发布)。
步骤 2:在 IIS 中配置虚拟目录指向 WebDAV
- 打开 IIS 管理器,选择你的站点。
- 添加虚拟目录:
- 右键站点 → 添加虚拟目录。
- 别名:任意名称(如
webdav-share
)。 - 物理路径:留空(因为我们要通过 HTTP 访问,而不是本地路径)。
- 配置 WebDAV 发布规则(如果 IIS 本身需要提供 WebDAV):
- 在站点上右键 → 添加 WebDAV 发布规则(如果目标是让 IIS 本身提供 WebDAV)。
- 但这里的目标是 访问外部 WebDAV,所以不需要这一步。
步骤 3:使用 IIS 的 URL Rewrite + Application Request Routing (ARR) 代理 WebDAV 请求
由于 IIS 不能直接挂载 HTTP 共享文件夹,但可以通过 URL Rewrite + ARR 代理 WebDAV 请求:
- 安装 ARR 和 URL Rewrite 模块:
- 下载并安装 IIS ARR (Application Request Routing) 和 URL Rewrite。
- 配置 ARR 代理:
- 在 IIS 管理器中,选择服务器节点 → Application Request Routing Cache → Server Proxy Settings → 勾选 Enable proxy。
- 添加 URL Rewrite 规则:
- 在站点上右键 → URL Rewrite → 添加规则 → 反向代理。
- 输入目标 WebDAV 地址(如
http://example.com/shared
)。 - 这样,IIS 可以通过
/webdav-share/
访问远程 WebDAV 文件夹。
步骤 4:测试访问
- 在浏览器或文件管理器中访问
http://your-iis-server/webdav-share/
,应该能看到远程共享文件夹的内容。 - 写入文件:如果 WebDAV 服务允许写入,可以直接上传文件。
C#使用 WebDAV 写入文件
WebDAV(Web Distributed Authoring and Versioning)是一种基于 HTTP/HTTPS 的文件共享协议,允许客户端远程访问和操作文件。在 C# 中,可以使用 WebDAVClient
库来实现文件上传。首先,需要通过 NuGet 安装 WebDAVClient
库
using System; using System.IO; using System.Net; using WebDAVClient; using WebDAVClient.Interfaces; class Program { static async Task Main() { string serverUrl = "https://your-webdav-server.com/"; string username = "your-username"; string password = "your-password"; string localFilePath = @"C:\path\to\local\file.txt"; string remoteFilePath = "/path/to/remote/file.txt"; try { await UploadFileAsync(serverUrl, username, password, localFilePath, remoteFilePath); Console.WriteLine("文件上传成功!"); } catch (Exception ex) { Console.WriteLine($"文件上传失败: {ex.Message}"); } } public static async Task UploadFileAsync(string serverUrl, string username, string password, string localFilePath, string remoteFilePath) { // 创建一个 WebDAV 客户端实例 IWebDAVClient client = new WebDAVClient.WebDAVClient(new Uri(serverUrl)); // 设置身份验证信息 if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) { client.SetCredentials(new NetworkCredential(username, password)); } // 确保远程路径存在 await client.MkcolAsync(remoteFilePath); // 上传文件 using (FileStream fileStream = File.OpenRead(localFilePath)) { await client.PutAsync(remoteFilePath, fileStream); } } }
3、使用 SFTP 写入文件
SFTP(SSH File Transfer Protocol)是一种基于 SSH 的安全文件传输协议。在 C# 中,可以使用 Renci.SshNet
库来实现 SFTP 文件上传。首先,需要通过 NuGet 安装 Renci.SshNet
库,示例代码如下
using System; using Renci.SshNet; class Program { static void Main() { string host = "your_host"; int port = 22; string username = "username"; string password = "password"; string localFilePath = @"C:\path\to\local\file.txt"; string remoteFilePath = "/remote/path/to/file.txt"; try { using (var client = new SftpClient(host, port, username, password)) { client.Connect(); using (var fileStream = System.IO.File.OpenRead(localFilePath)) { client.UploadFile(fileStream, remoteFilePath); } client.Disconnect(); Console.WriteLine("文件上传成功!"); } } catch (Exception ex) { Console.WriteLine($"文件上传失败: {ex.Message}"); } } }
4、 使用 FTPS 写入文件
FTPS(File Transfer Protocol over SSL/TLS)是 FTP 协议的安全版本,它使用 SSL/TLS 对数据进行加密。在 C# 中,可以使用 FtpWebRequest
类来实现 FTPS 文件上传,示例代码如下:
using System; using System.IO; using System.Net; class Program { static void Main() { string ftpServerIP = "ftp://your-ftp-server.com/"; string ftpUsername = "username"; string ftpPassword = "password"; string localFilePath = @"C:\path\to\local\file.txt"; string ftpPath = "remotefile.txt"; try { FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpServerIP + ftpPath); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(ftpUsername, ftpPassword); request.EnableSsl = true; request.UseBinary = true; request.UsePassive = true; using (FileStream fileStream = File.OpenRead(localFilePath)) using (Stream ftpStream = request.GetRequestStream()) { fileStream.CopyTo(ftpStream); } Console.WriteLine("文件上传成功!"); } catch (Exception ex) { Console.WriteLine($"文件上传失败: {ex.Message}"); } } }