EF Core中上传IFormFile到FTP服务器路径错误问题排查求助
问题排查
- 路径传参错误:Handler里传给
ImageUpload的path是@"\Image\Slider\"文件夹路径,不是具体文件路径。调用Path.GetFileName(path)只能拿到空值,导致FTP拼接的URL非法,同时File.OpenRead(path)尝试读取文件夹而非文件,直接触发路径错误。 - IFormFile未落地:拿到前端上传的
IFormFile对象后,没有先将文件内容写入本地对应路径,直接尝试读取不存在的本地文件,必然报错。 - 返回值逻辑错误:
ImageUpload方法固定返回null,会导致后续string.IsNullOrEmpty判断永远命中,直接返回文件类型不支持的错误,逻辑完全失效。 - 空判断顺序错误:在调用
_mapper.Map之后、使用mapped对象之后才判断mapped == null,顺序完全颠倒,就算映射失败也会先触发空引用异常。 - FTP地址不完整:代码里写的
@"cdnadress"不是合法的FTP地址前缀,需要补全ftp://开头的完整FTP服务地址。
提示:测试时请先确认FTP服务可以正常连接、对应目录有读写权限,同时替换代码中占位的FTP地址、账号密码、CDN前缀为实际业务值。
修复后的FileUpload扩展方法
public static class FileUpload { public static string ImageUpload(this IFormFile file, string directoryPath) { // 目录不存在则自动创建 if (!Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } // 生成不重名的文件名,避免覆盖旧文件 var fileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}"; var fullLocalPath = Path.Combine(directoryPath, fileName); // 将前端上传的文件写入本地路径 using (var localStream = new FileStream(fullLocalPath, FileMode.Create)) { file.CopyTo(localStream); } // 拼接合法FTP地址,注意补全ftp://前缀 var ftpUrl = @"ftp://替换为你的FTP服务地址/" + fileName; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(ftpUrl); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential("替换为FTP用户名", "替换为FTP密码"); request.UsePassive = true; request.UseBinary = true; request.KeepAlive = true; // 读取本地文件上传到FTP byte[] buffer; using (FileStream stream = File.OpenRead(fullLocalPath)) { buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); } using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(buffer, 0, buffer.Length); } // 返回可访问的资源地址,用CDN的话替换为CDN前缀即可 return ftpUrl; } }
修复后的SliderCreateHandler代码
public class SliderCreateHandler : IRequestHandler<SliderCreate, ApiResponse<SliderResponse>> { private readonly IUnitOfWork _repo; private readonly IMapper _mapper; public SliderCreateHandler(IUnitOfWork repo, IMapper mapper) { _repo = repo; _mapper = mapper; } public async Task<ApiResponse<SliderResponse>> Handle( SliderCreate request, CancellationToken cancellationToken) { // 先判断映射结果是否为空,再执行后续操作 var mapped = _mapper.Map<Slider>(request); if (mapped == null) return new ErrorApiResponse<SliderResponse>(ResultMessage.NotCreatedSlider); var path = Path.Combine(Environment.CurrentDirectory, @"Image\Slider\"); mapped.ImageUrl = request.file.ImageUpload(path); if (string.IsNullOrEmpty(mapped.ImageUrl)) return new ErrorApiResponse<SliderResponse>(ResultMessage.UnsupportedFileType); var model = await _repo.Sliders.AddAsync(mapped); var response = _mapper.Map<SliderResponse>(model); return new SuccessApiResponse<SliderResponse>(response); } }
内容的提问来源于stack exchange,提问作者user16695025
相关产品推荐
相关产品推荐

