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

本文关键字:请求 传输 文件 用户 缓冲 Net 内存 磁盘 ASP | 更新日期: 2023-09-27 18:28:39

这是我将用户输入文件上传到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中是新的。)

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

Ty获取答案!。

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

我搜索了一些帮助文章。但我没有声誉把它们联系起来!LOL

我用这种方法解决问题。

这是代码:

[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;
        }
    }

您的代码看起来非常好。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上——他只需要等待文件被上传到你的网络服务器。