业务场景:
应用程序服务器要与文件服务器分离,因此需要实现跨服务器操作附件,最终决定使用FTP方式
实现方式:
创建FileService类
public class FileService { //FTP路径 public static string url = "ftp://x.x.x.x/"; //FTP登录名 public static string loginName = "ftpuser"; //FTP密码 public static string passWord = "123456"; /// <summary> /// FTP上传 /// </summary> /// <param name="file">http获取到的文件</param> /// <param name="filename">文件名</param> /// <returns></returns> public static bool FtpUpload(HttpPostedFileBase file, string filename) { try { MemoryStream fs = new MemoryStream(); file.InputStream.CopyTo(fs); long length = fs.Length; FtpWebRequest ftpReq = (FtpWebRequest)FtpWebRequest.Create(new Uri(url + filename)); ftpReq.Credentials = new NetworkCredential(loginName, passWord); //默认为true,连接不会关闭,设置为false,执行之后关闭连接 ftpReq.KeepAlive = false; ftpReq.Method = WebRequestMethods.Ftp.UploadFile; ftpReq.UseBinary = true; ftpReq.UsePassive = false; Stream fsftp = ftpReq.GetRequestStream(); //设置缓冲大小 int BufferLength = 5120; byte[] b = new byte[BufferLength]; fs.Seek(0, SeekOrigin.Begin); int i; while ((i = fs.Read(b, 0, BufferLength)) > 0) { fsftp.Write(b, 0, i); } return true; } catch (Exception ex) { return false; } } /// <summary> /// 获取附件文件流 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static byte[] FtpDownload(string fileName) { try { MemoryStream outputStream = new MemoryStream(); FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(url + fileName)); ftp.Method = WebRequestMethods.Ftp.DownloadFile; ftp.UseBinary = true; ftp.UsePassive = false; ftp.Credentials = new NetworkCredential(loginName, passWord); FtpWebResponse response = (FtpWebResponse)ftp.GetResponse(); Stream ftpStream = response.GetResponseStream(); int bufferSize = 2048; int readCount; byte[] buffer = new byte[bufferSize]; readCount = ftpStream.Read(buffer, 0, bufferSize); while (readCount > 0) { outputStream.Write(buffer, 0, readCount); readCount = ftpStream.Read(buffer, 0, bufferSize); } byte[] file = outputStream.GetBuffer(); ftpStream.Close(); outputStream.Close(); response.Close(); return file; } catch (Exception ex) { return null; } } }View Code
Controller代码
1 /// <summary> 2 /// 上传 3 /// </summary> 4 /// <returns></returns> 5 public ActionResult Upload() 6 { 7 8 if (Request.Files.Count == 0) 9 { 10 //Request.Files.Count 文件数为0上传不成功 11 return Content("上传文件失败,请重新选择!"); 12 } 13 var file = Request.Files[0]; 14 if (file.ContentLength == 0) 15 { 16 //文件大小大(以字节为单位)为0时,做一些操作 17 return Content("上传文件失败,请重新选择!"); 18 } 19 string filename = DateTime.Now.ToString("ffffff") + file.FileName;//取得文件名字 20 return FileService.FtpUpload(file, filename)! ? Content("操作成功!") : Content("上传文件失败,请重新选择!"); 21 } 22 23 24 25 /// <summary> 26 /// 下载 27 /// </summary> 28 /// <param name="filename"></param> 29 /// <returns></returns> 30 public ActionResult Download(string filename) 31 { 32 var file = FileService.FtpDownload(filename); 33 Stream stream = new MemoryStream(file); 34 stream.Read(file, 0, file.Length); 35 stream.Close(); 36 Response.Charset = "UTF-8"; 37 Response.ContentType = "application/octet-stream"; 38 Response.ContentEncoding = Encoding.GetEncoding("GB2312"); 39 Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename)); 40 Response.BinaryWrite(file); 41 Response.Flush(); 42 Response.End(); 43 return new EmptyResult(); 44 }View Code
调试期间一直报错:227 Entering Passive Mode
网上查了半天也没得到解决方案,最后在一个2008年的老帖子里发现,是FTP访问模式问题,FtpWebRequest默认是被动模式,需要手动改成主动模式,所以多加一行ftpReq.UsePassive = false;就可以了
原文链接:The remote server returned an error: 227 Entering Passive Mode (67,228,53,42,12,130) (microsoft.com)