- A+
项目中经常涉及到将文件批量上传到其它空间或服务器,这个时候我们有可能需要用到FTP协议进行传输,所以这里我推荐使用FluentFTP,一款很好用的FTP传输框架。
github地址:https://github.com/robinrodricks/FluentFTP
Nuget安装一下:
PM> Install-Package FluentFTP
首先new一个Client:
1 /* 2 第一个参数是FTP地址,注意要加协议名 3 第二个参数是端口,默认21 4 第三个参数是FTP用户名 5 第四个参数是FTP密码 6 正常情况下配置三个属性即可,大家按需选择: 7 EncryptionMode是指定加密方式,这里我选择None不加密, 8 DataConnectionType是连接方式,一般都是选PASV被动模式或PORT主动模式,根据FTPServer情况修改 9 Encoding是指定编码 10 */ 11 var ftpClient = new FtpClient($"ftp://{host}", port, userName, passWord) 12 { 13 EncryptionMode = FtpEncryptionMode.None, 14 DataConnectionType = FtpDataConnectionType.PASV, 15 Encoding = Encoding.UTF8 16 };
接下来第一步,登录FTP:
1 //IsConnected是判断client是否与远程服务建立了连接 2 if (!ftpClient.IsConnected) 3 { 4 //发起连接登录 5 await ftpClient.ConnectAsync(); 6 //启用UTF8传输 7 var result = ftpClient.Execute("OPTS UTF8 ON"); 8 if (!result.Code.Equals("200") && !result.Code.Equals("202")) 9 ftpClient.Encoding = Encoding.GetEncoding("ISO-8859-1"); 10 }
这里有一个比较坑的地方,不了解FTP的伙伴有可能会纠结半天,那就是文件如果是中文文件名,上传后文件名会变成乱码。原因是因为有一些FTPServer默认是不开启UTF8编码传输,甚至不支持UTF8编码传输,这个时候需要我们手动开启一下,FTP命令是OPTS UTF8 ON
ftpClient.Execute("OPTS UTF8 ON");
这个时候会服务器会返回一个状态码,200表示开启成功;202是always enable,表示FTPServer会一直处于开启状态,不需要手动开启。
但除此之外,还有刚才提到的,FTPServer本身不支持这种UTF8编码的传输,这个时候我们需要将之前的Encoding设置为ISO-8859-1。
ftpClient.Encoding = Encoding.GetEncoding("ISO-8859-1");
第二步,上传文件:
1 /// <summary> 2 /// 上传单个文件 3 /// </summary> 4 /// <param name="sourcePath">文件源路径</param> 5 /// <param name="destPath">上传到指定的ftp文件夹路径</param> 6 public async void UploadFile(string sourcePath, string destPath) 7 { 8 if (!File.Exists(sourcePath)) 9 return; 10 var fileInfo = new FileInfo(sourcePath); 11 await ftpClient.UploadFileAsync(sourcePath, destPath, createRemoteDir: true); 12 }
如果想批量上传,则使用ftpClient.UploadDirectoryAsync(),可以直接上传整个文件夹;这里有个比较坑的地方是,如果FTPServer目录下的文件特别多(不是指你上传文件的数量),上传所需的时间会特别长。在我查看了FTP日志后发现,在使用UploadDirectoryAsync()的时候,FluentFTP会先去获取所有文件和文件夹的列表,在尝试解决无果后,我去github上找了一下,作者的回复是:
Currently we support 2 modes, update and mirror. In any mode, the remote directory is fully listed, then compared, then the actually upload begins. This is done in order to skip files that are already uploaded. We can support a third mode, maybe like BlindTransfer which will not list the remote directory.
google翻译:目前,我们支持2种模式:更新和镜像。 在任何模式下,远程目录都会完整列出,然后进行比较,然后开始实际的上载。 这样做是为了跳过已经上传的文件。 我们可以支持第三种模式,例如BlindTransfer,它不会列出远程目录。
但在目前最新版本33.0.3版本下,仍旧只支持Mirror和Update。
Issues:https://github.com/robinrodricks/FluentFTP/issues/616
所以,如果需要批量上传,可以在单文件上传的基础上自己再做一层封装,至于其它的下载、删除、查看等功能,暂未发现其它的坑,环境.net core 3.1。
这里只举几个常用的方法,其余的不在这里赘述,大家看文档和框架的注释就行:
//下载文件 ftpClient.DownloadFileAsync(); //下载文件夹 ftpClient.DownloadDirectoryAsync(); //删除文件 ftpClient.DeleteFileAsync(); //删除文件夹 ftpClient.DeleteDirectoryAsync(); //判断文件是否存在 ftpClient.FileExistsAsync(); //判断文件夹是否存在 ftpClient.DirectoryExistsAsync(); //获取列表的详细信息 ftpClient.GetListingAsync();
最后,记住登出、释放资源:
1 if (ftpClient.IsConnected) 2 { 3 //关闭 4 await ftpClient.DisconnectAsync(); 5 ftpClient.Dispose(); 6 }