WebApi 上传附件到 ftp 服务器

2019-01-03 03:33发布

想要实现的功能:Post附件到WebApi,WebApi 将文件转发到 ftp服务器。

主要功能已经实现,有一个问题:需要在WebApi服务器,接收流写入WebApi本地文件,然后读取文件流写入 ftp 服务器,然后再删除WebApi 服务器上的本地文件,现在不想在WebApi本地写文件,直接取Request的流写入到 ftp,不知道能不能实现,应该怎样写?

 

1. Post附件到WebApi 主要代码:

#region 上传文件

        /// <summary>
        /// 通过multipart/form-data方式上传文件
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<HttpResponseMessage> PostFile()
        {
            MessagesDataCodeModel json = new MessagesDataCodeModel(false"无效参数", 401);
 
            try
            {
                // 是否请求包含multipart/form-data。
                if (!Request.Content.IsMimeMultipartContent())
                {
                    logger.Error("上传格式不是multipart/form-data");
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                }
 
                string root = HttpContext.Current.Server.MapPath("/UploadFiles/");
                if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/UploadFiles/")))
                {
                    Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/UploadFiles/"));
                }
 
                var provider = new MultipartFormDataStreamProvider(root);
 
                StringBuilder sb = new StringBuilder(); // Holds the response body
 
                // 阅读表格数据并返回一个异步任务.
                await Request.Content.ReadAsMultipartAsync(provider);
 
                // 如何上传文件到文件名.
                foreach (var file in provider.FileData)
                {
                    string orfilename = file.Headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"');
                    FileInfo fileinfo = new FileInfo(file.LocalFileName);
                    //sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
                    //最大文件大小
                    //int maxSize = Convert.ToInt32(SettingConfig.MaxSize);
                    if (fileinfo.Length <= 0)
                    {
                        json.Success = false;
                        json.Msg = "请选择上传文件";
                        json.Code = 301;
                    }
                    else if (fileinfo.Length > ConfigHelper.MaxFileSize)
                    {
                        json.Msg = "上传文件大小超过限制";
                        json.Code = 302;
                    }
                    else
                    {
                        string fileExt = orfilename.Substring(orfilename.LastIndexOf('.'));
                        //定义允许上传的文件扩展名
                        //String fileTypes = SettingConfig.FileTypes;
                        //if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(fileTypes.Split(','), fileExt.Substring(1).ToLower()) == -1)
                        //{
                        //    json.Msg = "图片类型不正确";
                        //    json.Code = 303;
                        //}
                        //else
                        //{
                        //String ymd = DateTime.Now.ToString("yyyyMMdd", System.Globalization.DateTimeFormatInfo.InvariantInfo);
                        //String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", System.Globalization.DateTimeFormatInfo.InvariantInfo);
 
                        fileinfo.CopyTo(Path.Combine(root, fileinfo.Name + fileExt), true);
                        json.Success = true;
                        json.Msg = "操作成功";
                        json.Code = 200;
                        sb.Append("/UploadFiles/" + fileinfo.Name + fileExt);
                        json.Data = sb.ToString();
                        //}
                    }
                    fileinfo.Delete();//删除原文件
                }
            }
            catch (System.Exception e)
            {
                json.Success = false;
                json.Msg = "服务器无响应";
                json.Code = 500;
                logger.Error("PostFile()服务器错误", e);
            }
            return ToJsonTran.ToJson(json);
        }
        #endregion 上传文件
 
2. 上传到 ftp服务器

/// <summary>
/// 上传文件
/// </summary>
/// <param name="fileinfo">需要上传的文件</param>
/// <param name="targetDir">目标路径</param>
/// <param name="hostname">ftp地址</param>
/// <param name="username">ftp用户名</param>
/// <param name="password">ftp密码</param>
public static void UploadFile(FileInfo fileinfo, string targetDir, string hostname, string username, string password)
{
//1. check target
string target;
if (targetDir.Trim() == "")
{
return;
}
target = Guid.NewGuid().ToString(); //使用临时文件名

string URI = "FTP://" + hostname + "/" + targetDir + "/" + target;
///WebClient webcl = new WebClient();
System.Net.FtpWebRequest ftp = GetRequest(URI, username, password);

//设置FTP命令 设置所要执行的FTP命令,
//ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;//假设此处为显示指定路径下的文件列表
ftp.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
//指定文件传输的数据类型
ftp.UseBinary = true;
ftp.UsePassive = true;

//告诉ftp文件大小
ftp.ContentLength = fileinfo.Length;
//缓冲大小设置为2KB
const int BufferSize = 2048;
byte[] content = new byte[BufferSize - 1 + 1];
int dataRead;

//打开一个文件流 (System.IO.FileStream) 去读上传的文件
using (FileStream fs = fileinfo.OpenRead())
{
try
{
//把上传的文件写入流
using (Stream rs = ftp.GetRequestStream())
{
do
{
//每次读文件流的2KB
dataRead = fs.Read(content, 0, BufferSize);
rs.Write(content, 0, dataRead);
} while (!(dataRead < BufferSize));
rs.Close();
}

}
catch (Exception ex) { }
finally
{
fs.Close();
}

}

ftp = null;
//设置FTP命令
ftp = GetRequest(URI, username, password);
ftp.Method = System.Net.WebRequestMethods.Ftp.Rename; //改名
ftp.RenameTo = fileinfo.Name;
try
{
ftp.GetResponse();
}
catch (Exception ex)
{
ftp = GetRequest(URI, username, password);
ftp.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
ftp.GetResponse();
throw ex;
}
finally
{
//fileinfo.Delete();
}

// 可以记录一个日志 "上传" + fileinfo.FullName + "上传到" + "FTP://" + hostname + "/" + targetDir + "/" + fileinfo.Name + "成功." );
ftp = null;

#region
/*****
*FtpWebResponse
* ****/
//FtpWebResponse ftpWebResponse = (FtpWebResponse)ftp.GetResponse();
#endregion
}

2条回答
啃猪蹄的小仙女
2楼-- · 2019-01-03 03:49

我记得当初我也有个类似的问题:页面请求服务器下载文件,但文件在微软的云上,这中间就导致一个文件经过服务器的手中转了一次,服务器先从云上下载,然后浏览器再从服务器下载.....

当时是服务器构造一个HttpWebRequest直接请求云上的文件。

 

但这个情况有点不同,毕竟浏览器是向http服务器上post,不管怎样,文件流已经到了服务器,不论服务器接受不接受(时间已经花费了),当然服务器可以选择不存储在本地,直接将流导向ftp服务器。具体代码我不清楚,没接触ftp相关的东西,思路应该可以借鉴下。

其实存http服务器本地这一步确实有点多余:把文件流写入文件,又读取同一文件的文件流。

查看更多
Fickle 薄情
3楼-- · 2019-01-03 03:56

肯定可以。直接操作context request 中的stream即可。

查看更多
登录 后发表回答