如何在ASP.Net的内存或磁盘中流式传输用户请求中的文件而不缓冲请求

时间:2015-12-31 14:32:08

标签: c# asp.net-mvc

这是我将用户输入文件上传到ftp服务器的代码:

 public static bool UploadFile(string FilePath, HttpPostedFileBase file)
    {
        Stream ftpStream = null;
        FtpWebRequest request = null;
        FtpWebResponse response = null;            
        try
        {
            FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpURL + FilePath);
            ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
            ftpRequest.Credentials = new NetworkCredential(UserName, Password);
            ftpRequest.ContentLength = file.ContentLength;
            Stream requestStream = ftpRequest.GetRequestStream();

            Byte[] buffer = new Byte[buferSize];
            int bytesRead = file.InputStream.Read(buffer, 0, buferSize);
            while (bytesRead > 0)
            {
                requestStream.Write(buffer, 0, bytesRead);
                bytesRead = file.InputStream.Read(buffer, 0, buferSize);
            }
            requestStream.Close();
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

似乎工作正常。但有一个问题。 当用户尝试上传文件时(一个大文件!) 它需要很长时间(我认为在主机服务器内存或磁盘中保存文件!) 并采取另一个!很长时间以ftp上传。 现在问题是我可以直接通过我的主机将用户输入文件上传到ftp服务器。我的意思是使用HttpPostedFile,我有一个来自文件的流,将其保存在Ftp服务器中,减少上传文件的时间。

(抱歉语言和信息不好!我是MVC新手。)

2 个答案:

答案 0 :(得分:1)

您的代码看起来非常好。 HttpPostedFileBase只是包含文件数据的底层网络流的指针(流)。此文件永远不会在内存中完全读取,因为您只是从底层TCP套接字读取块:这也是非常好用和高效的。您也可以直接将已读取的字节块复制到远程FTP服务器上的传出套接字。除了提高不同跃点之间的网络速度之外,优化此代码的工作并不多。

我只能使用Stream.CopyTo方法提出代码的语法简化:

var ftpRequest = (FtpWebRequest)WebRequest.Create(ftpURL + FilePath);
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Credentials = new NetworkCredential(UserName, Password);
ftpRequest.ContentLength = file.ContentLength;
using (Stream requestStream = ftpRequest.GetRequestStream())
{
    file.InputStream.CopyTo(requestStream);
}
return true;

如果与此FTP服务器的网络连接速度很慢而您无法控制这一小改进,我可以想到将上传的文件存储在您的网络服务器上,然后有一些后台作业将运行并将其上传到远程FTP服务器。这样客户端就不需要等待文件上传到FTP上 - 他只需要等待文件上传到您的Web服务器。

答案 1 :(得分:1)

Ty的答案!

主要问题是缓冲内存(和磁盘)中的所有请求。

我搜索并找到一些帮助全文。但我没有名声可以链接他们! LOL

我用this way来解决问题。

这是代码:

[RequestAuthorized(CurrentUser = UserTypes.AdminDeveloper)]
 public async Task<ActionResult> Create_Step4()
    {
        ...blabla
        var requestStream = HttpContext.Request.GetBufferlessInputStream();
        var mpp = new MultipartPartParser(requestStream);
        long fileSize = FTPUtility.UploadFile(FilePath, mpp);
    }

    public static long UploadFile(string FilePath, MultipartPartParser file)
    {           
        try
        {
            FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpURL + FilePath.Substring(1).Replace('\\', '/'));
            ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
            ftpRequest.Credentials = new NetworkCredential(UserName, Password);

            Stream requestStream = ftpRequest.GetRequestStream();
            long fileSize = 0;
            Byte[] buffer = new Byte[buferSize];
            int bytesRead = file.Read(buffer, 0, buferSize);
            fileSize += bytesRead;
            while (bytesRead > 0)
            {
                requestStream.Write(buffer, 0, bytesRead);
                bytesRead = file.Read(buffer, 0, buferSize);
                fileSize += bytesRead;
            }
            requestStream.Close();

            return fileSize;
        }
        catch (Exception)
        {
            return -1;
        }
    }