C#:替代过时FtpWebRequest实现FTP文件上传的方案
FTP文件上传:替代过时FtpWebRequest的解决方案
问题背景
需要通过FTP协议将本地文件复制到本地或远程文件夹,原使用FtpWebRequest的代码已被标记为过时,公司要求改用HttpClient,但尝试用MultipartFormDataContent实现时发现HttpClient不支持FTP协议,最终通过第三方库FluentFTP解决问题。
原过时代码(基于FtpWebRequest)
[Obsolete("Obsolete")] private async Task UploadFile(FileDescriptionModel descriptionModel, FtpConfigModel configModel) { try { var filePath = $"ftp://{configModel.Ip}:{configModel.Port}/{descriptionModel.RelativePath}"; _logger.LogInformation("Started creating file"); using var ms = new MemoryStream(await File.ReadAllBytesAsync(descriptionModel.FilePath)); ms.Position = 0; ms.ToArray(); _logger.LogInformation("Started connection to {ipPath}", filePath); var ftpWebRequest = (FtpWebRequest)WebRequest.Create(filePath); ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile; ftpWebRequest.Credentials = new NetworkCredential(configModel.User, configModel.Password); // convert contents to byte. await using Stream requestStream = ftpWebRequest.GetRequestStream(); _logger.LogInformation("Started uploading"); await ms.CopyToAsync(requestStream); _logger.LogInformation("Finished uploading"); } catch (Exception e) { _logger.LogError("Stream cannot be read", e); throw; } }
尝试的HttpClient方案(无法运行)
此方案失败的核心原因是:HttpClient仅支持HTTP/HTTPS协议,无法处理FTP请求,调用PostAsync传入ftp://开头的地址会直接报错。
private async Task<string> UploadFile2(FileDescriptionModel descriptionModel, FtpConfigModel configModel) { var filePath = $"ftp://{configModel.Ip}:{configModel.Port}/{descriptionModel.RelativePath}"; var httpClient = new HttpClient(); httpClient.SetBasicAuthentication(configModel.User, configModel.Password); using (var multipartFormContent = new MultipartFormDataContent()) { //Add other fields using var ms = new MemoryStream(await File.ReadAllBytesAsync(descriptionModel.FilePath)); multipartFormContent.Add(new ByteArrayContent(ms.ToArray()), name: "SomeName", fileName: descriptionModel.RelativePath); //Send it var response = await httpClient.PostAsync(filePath, multipartFormContent); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } }
最终可行方案(基于FluentFTP)
使用第三方库FluentFTP,它专门针对FTP协议封装了简洁的API,支持异步操作,且无需手动处理复杂的FTP连接逻辑。
private async Task UploadFile3(FileDescriptionModel descriptionModel, FtpConfigModel configModel) { var client = new AsyncFtpClient(configModel.Ip, configModel.User, configModel.Password, configModel.Port); // 连接服务器并自动检测适配的FTP设置 await client.AutoConnect(); // 上传文件 var status = await client.UploadFile(descriptionModel.FilePath, $"{descriptionModel.RelativePath}"); }
内容的提问来源于stack exchange,提问作者Aleksandar Trifunović
相关产品推荐
相关产品推荐

