2

This is my Code for uploading user input file to a ftp server:

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

and it seems work fine. but there is a problem. when user try to upload a file (a big one!) its takes a long time (to save file in host server memory or disk i think!) and take another! long time to upload in ftp. now the question is can i upload user input file through my host to ftp server directly. i mean instead using HttpPostedFile i have a stream from file to save it in Ftp server and reduce upload file time.

(Sorry for poor language and info!. im new in MVC.)

2 Answers 2

2

Ty for answers!.

the main problem was buffering all request in memory (and disk).

i searched and found some help full articles. but i have no reputation to link them! LOL

at all i used this way to solve problem.

this is code:

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

and

    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;
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

1

Your code looks very good. The HttpPostedFileBase is just a pointer (stream) to the underlying network stream that contains the file data. This file is never entirely read in memory because you are only reading in chunks from the underlying TCP socket: this is also very good and efficient. Also you are directly copying the chunk of bytes you have read to the outgoing socket on the remote FTP server. There's not much that can be done to optimize this code other than improving the network speed between the different hops.

I can only propose syntactic simplification of your code by using the Stream.CopyTo method:

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;

If the network connection to this FTP server is slow and you cannot contorl this one small improvement I can think of is storing the uploaded file on your webserver and then have some background job that will run and upload it to the remote FTP server. This way the client wouldn't need to wait for the file to be uploaded on the FTP - he will only need to wait for the file to be uploaded to your web server.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.