예제 #1
0
 protected override void OnInit()
 {
     base.OnInit();
     Context               = new FtpContext();
     Context.Charset       = this.Charset;
     Context.TempDirectory = this.AppServer.FtpServiceProvider.GetTempDirectory(this.SessionID);
 }
예제 #2
0
        public bool Logon(FtpContext context, FtpUser user)
        {
            FtpUser onlineUser = null;

            lock (m_SyncRoot)
            {
                m_DictOnlineUser.TryGetValue(user.UserName, out onlineUser);
            }

            if (onlineUser != null)
            {
                context.User = onlineUser;
                return(onlineUser.IncreaseConnection());
            }
            else
            {
                user.IncreaseConnection();
                context.User = user;

                lock (m_SyncRoot)
                {
                    m_DictOnlineUser[user.UserName] = user;
                }

                return(true);
            }
        }
        public virtual bool DeleteFile(FtpContext context, string filename)
        {
            string filepath = GetStoragePath(context, filename);

            if (File.Exists(filepath))
            {
                FileInfo file = new FileInfo(filepath);

                long fileLength = file.Length;

                try
                {
                    File.Delete(filepath);
                    context.ChangeSpace(0 - fileLength);
                    return(true);
                }
                catch (UnauthorizedAccessException uae)
                {
                    AppServer.Logger.Error(uae);
                    context.SetError(FtpCoreResource.PermissionDenied_550);
                    return(false);
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.DeleteFailed_450, filename);
                    return(false);
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return(false);
            }
        }
예제 #4
0
        /// <summary>
        /// Gets the stream.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public Stream GetStream(FtpContext context)
        {
            if (m_Stream == null)
            {
                InitStream(context);
            }

            return(m_Stream);
        }
        /// <summary>
        /// Gets the stream.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public Stream GetStream(FtpContext context)
        {
            if (m_Stream == null)
            {
                InitStream(context);
            }

            return m_Stream;
        }
        protected List <ListItem> GetList(FtpContext context, string dir)
        {
            List <ListItem> list = new List <ListItem>();

            if (Directory.Exists(dir))
            {
                string[] files = Directory.GetFiles(dir);

                if (files != null)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        FileInfo file = new FileInfo(files[i]);
                        ListItem item = new ListItem();

                        item.ItemType         = ItemType.File;
                        item.LastModifiedTime = file.LastWriteTime;
                        item.Length           = file.Length;
                        item.Name             = file.Name;
                        item.OwnerName        = context.UserName;
                        item.Permission       = "-rwx------";
                        list.Add(item);
                    }
                }

                string[] folders = Directory.GetDirectories(dir);

                if (folders != null)
                {
                    for (int i = 0; i < folders.Length; i++)
                    {
                        DirectoryInfo folder = new DirectoryInfo(folders[i]);
                        ListItem      item   = new ListItem();

                        item.ItemType         = ItemType.Folder;
                        item.LastModifiedTime = folder.LastWriteTime;
                        item.Length           = 0;
                        item.Name             = folder.Name;
                        item.OwnerName        = context.UserName;
                        item.Permission       = "drwx------";

                        list.Add(item);
                    }
                }

                return(list);
            }
            else
            {
                AppServer.Logger.ErrorFormat("{0} was not found.", dir);
                context.SetError(FtpCoreResource.NotFound_550);
                return(null);
            }
        }
예제 #7
0
        public void SendResponse(FtpContext context, List <ListItem> list)
        {
            Stream stream = GetStream(context);

            if (list == null || list.Count <= 0)
            {
                return;
            }

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < list.Count; i++)
            {
                sb.Append(list[i].Permission);

                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);

                sb.Append("1");
                sb.Append(DELIM);
                sb.Append("user");
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append("group");

                sb.Append(DELIM);

                sb.Append(GetFixedLength(list[i].Length));

                sb.Append(DELIM);

                sb.Append(GetListTimeString(list[i].LastModifiedTime));

                sb.Append(DELIM);

                sb.Append(list[i].Name);

                sb.Append(NEWLINE);

                byte[] data = context.Charset.GetBytes(sb.ToString());
                stream.Write(data, 0, data.Length);

                sb.Remove(0, sb.Length);
            }

            stream.Flush();
        }
        public virtual bool IsExistFile(FtpContext context, string filepath)
        {
            string path = GetStoragePath(context, filepath);

            try
            {
                return(File.Exists(path));
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError(FtpCoreResource.FileSystemError_450);
                return(false);
            }
        }
 private void InitStream(FtpContext context)
 {
     switch (SecureProtocol)
     {
         case (SslProtocols.Tls):
         case (SslProtocols.Ssl3):
         case (SslProtocols.Ssl2):
             SslStream sslStream = new SslStream(new NetworkStream(Client), false);
             sslStream.AuthenticateAsServer(m_Session.AppServer.Certificate, false, SslProtocols.Default, true);
             m_Stream = sslStream as Stream;
             break;
         default:
             m_Stream = new NetworkStream(Client);
             break;
     }
 }
예제 #10
0
        private void InitStream(FtpContext context)
        {
            switch (SecureProtocol)
            {
            case (SslProtocols.Tls):
            case (SslProtocols.Ssl3):
            case (SslProtocols.Ssl2):
                SslStream sslStream = new SslStream(new NetworkStream(Client), false);
                sslStream.AuthenticateAsServer(m_Session.AppServer.Certificate, false, SslProtocols.Default, true);
                m_Stream = sslStream as Stream;
                break;

            default:
                m_Stream = new NetworkStream(Client);
                break;
            }
        }
        public virtual bool RenameFolder(FtpContext context, string oldPath, string newPath)
        {
            oldPath = GetStoragePath(context, oldPath);
            newPath = GetStoragePath(context, newPath);

            try
            {
                Directory.Move(oldPath, newPath);
                return(true);
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError(FtpCoreResource.RenameDirectoryFailed_553);
                return(false);
            }
        }
        public virtual bool IsExistFolder(FtpContext context, string path)
        {
            string dir = GetStoragePath(context, path);

            try
            {
                bool result = Directory.Exists(dir);

                if (!result)
                {
                    AppServer.Logger.Error("The directory: " + dir + " was not found");
                }

                return(result);
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError(FtpCoreResource.FileSystemError_450);
                return(false);
            }
        }
        protected string GetStoragePath(FtpContext context, string virtualPath)
        {
            if (!virtualPath.StartsWith("/"))
            {
                if (context.CurrentPath != "/")
                {
                    virtualPath = context.CurrentPath + "/" + virtualPath;
                }
                else
                {
                    virtualPath = context.CurrentPath + virtualPath;
                }
            }

            //Windows path
            if (Path.DirectorySeparatorChar == '\\')
            {
                virtualPath = SuperSocket.Ftp.FtpCommon.StringUtil.ReverseSlash(virtualPath, '/');
            }

            return(GetStoragePathInternal(context, virtualPath));
        }
        public virtual DateTime GetModifyTime(FtpContext context, string filename)
        {
            string filepath = GetStoragePath(context, filename);

            if (File.Exists(filepath))
            {
                try
                {
                    FileInfo file = new FileInfo(filepath);
                    return(file.LastWriteTime);
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.FileUnavailable_550);
                    return(DateTime.MinValue);
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return(DateTime.MinValue);
            }
        }
        public virtual long GetFileSize(FtpContext context, string filename)
        {
            string filepath = GetStoragePath(context, filename);

            if (File.Exists(filepath))
            {
                try
                {
                    FileInfo file = new FileInfo(filepath);
                    return(file.Length);
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.FileUnavailable_550);
                    return(0);
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return(0);
            }
        }
        public virtual bool CreateFolder(FtpContext context, string foldername)
        {
            string dir = GetStoragePath(context, foldername);

            if (Directory.Exists(dir) || File.Exists(dir))
            {
                context.SetError(FtpCoreResource.DirectoryAlreadyExist_550, foldername);
                return(false);
            }
            else
            {
                try
                {
                    Directory.CreateDirectory(dir);
                    return(true);
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.MakeDirFailed_550, foldername);
                    return(false);
                }
            }
        }
        public virtual bool RemoveFolder(FtpContext context, string foldername)
        {
            string dir = GetStoragePath(context, foldername);

            if (Directory.Exists(dir))
            {
                try
                {
                    Directory.Delete(dir);
                    return(true);
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.RemoveDirectoryFailed_550, foldername);
                    return(false);
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return(false);
            }
        }
 public virtual bool StoreFile(FtpContext context, string filename, Stream stream)
 {
     return(StoreFile(context, filename, stream, new StoreOption()));
 }
 public abstract long GetUserRealUsedSpace(FtpContext context, string username);
        public virtual bool RemoveFolder(FtpContext context, string foldername)
        {
            string dir = GetStoragePath(context, foldername);

            if (Directory.Exists(dir))
            {
                try
                {
                    Directory.Delete(dir);
                    return true;
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.RemoveDirectoryFailed_550, foldername);
                    return false;
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return false;
            }
        }
        public virtual long GetFileSize(FtpContext context, string filename)
        {
            string filepath = GetStoragePath(context, filename);

            if (File.Exists(filepath))
            {
                try
                {
                    FileInfo file = new FileInfo(filepath);
                    return file.Length;
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.FileUnavailable_550);
                    return 0;
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return 0;
            }
        }
 protected virtual string GetStoragePathInternal(FtpContext context, string virtualPath)
 {
     virtualPath = virtualPath.TrimStart(Path.DirectorySeparatorChar);
     return Path.Combine(context.User.Root, virtualPath);
 }
 public abstract long GetUserRealUsedSpace(FtpContext context, string username);
        public virtual bool IsExistFolder(FtpContext context, string path)
        {
            string dir = GetStoragePath(context, path);

            try
            {
                bool result = Directory.Exists(dir);

                if (!result)
                {
                    AppServer.Logger.Error("The directory: " + dir + " was not found");
                }

                return result;
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError(FtpCoreResource.FileSystemError_450);
                return false;
            }
        }
        public virtual List <ListItem> GetList(FtpContext context)
        {
            string dir = GetStoragePath(context, context.CurrentPath);

            return(GetList(context, dir));
        }
예제 #26
0
 public override void ClearTempDirectory(FtpContext context)
 {
     //Do nothing
 }
예제 #27
0
 public override long GetUserRealUsedSpace(FtpContext context, string username)
 {
     string userStorageRoot = context.User.Root;
     return GetDirectorySize(userStorageRoot);
 }
        public virtual bool IsExistFile(FtpContext context, string filepath)
        {
            string path = GetStoragePath(context, filepath);

            try
            {
                return File.Exists(path);
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError(FtpCoreResource.FileSystemError_450);
                return false;
            }
        }
 public virtual bool StoreFile(FtpContext context, string filename, Stream stream)
 {
     return StoreFile(context, filename, stream, new StoreOption());
 }
        protected bool StoreFile(FtpContext context, string filename, Stream stream, StoreOption option)
        {
            int bufLen = 1024 * 10;

            byte[] buffer    = new byte[bufLen];
            int    read      = 0;
            long   totalRead = 0;

            int speed = context.User.MaxUploadSpeed;

            FileStream fs = null;

            try
            {
                string filePath = GetStoragePath(context, filename);

                if (context.Offset > 0 && option.AppendOriginalFile) //Append
                {
                    FileInfo file = new FileInfo(filePath);

                    if (context.Offset != file.Length)
                    {
                        context.Status  = FtpStatus.Error;
                        context.Message = "Invalid offset";
                        return(false);
                    }

                    fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Write, bufLen);
                }
                else
                {
                    if (File.Exists(filePath))
                    {
                        FileInfo file       = new FileInfo(filePath);
                        var      fileLength = file.Length;
                        File.Delete(filePath);
                        context.ChangeSpace(0 - fileLength);
                    }

                    fs = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Write, bufLen);
                }


                DateTime dtStart;
                TimeSpan ts;
                int      usedMs = 0, predictMs = 0;

                dtStart = DateTime.Now;

                while ((read = stream.Read(buffer, 0, bufLen)) > 0)
                {
                    fs.Write(buffer, 0, read);
                    totalRead += read;
                    context.ChangeSpace(read);

                    if (speed > 0) // if speed <=0, then no speed limitation
                    {
                        ts        = DateTime.Now.Subtract(dtStart);
                        usedMs    = (int)ts.TotalMilliseconds;
                        predictMs = read / speed;

                        if (predictMs > usedMs) //Speed control
                        {
                            Thread.Sleep(predictMs - usedMs);
                        }

                        dtStart = DateTime.Now;
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.Status  = FtpStatus.Error;
                context.Message = "Store file error";
                return(false);
            }
            finally
            {
                option.TotalRead = totalRead;

                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
            }
        }
        protected List<ListItem> GetList(FtpContext context, string dir)
        {
            List<ListItem> list = new List<ListItem>();

            if (Directory.Exists(dir))
            {
                string[] files = Directory.GetFiles(dir);

                if (files != null)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        FileInfo file = new FileInfo(files[i]);
                        ListItem item = new ListItem();

                        item.ItemType = ItemType.File;
                        item.LastModifiedTime = file.LastWriteTime;
                        item.Length = file.Length;
                        item.Name = file.Name;
                        item.OwnerName = context.UserName;
                        item.Permission = "-rwx------";
                        list.Add(item);
                    }
                }

                string[] folders = Directory.GetDirectories(dir);

                if (folders != null)
                {
                    for (int i = 0; i < folders.Length; i++)
                    {
                        DirectoryInfo folder = new DirectoryInfo(folders[i]);
                        ListItem item = new ListItem();

                        item.ItemType = ItemType.Folder;
                        item.LastModifiedTime = folder.LastWriteTime;
                        item.Length = 0;
                        item.Name = folder.Name;
                        item.OwnerName = context.UserName;
                        item.Permission = "drwx------";

                        list.Add(item);
                    }
                }

                return list;
            }
            else
            {
                AppServer.Logger.ErrorFormat("{0} was not found.", dir);
                context.SetError(FtpCoreResource.NotFound_550);
                return null;
            }
        }
 public abstract void ClearTempDirectory(FtpContext context);
        public virtual bool ReadFile(FtpContext context, string filename, Stream stream)
        {
            int bufLen = 1024 * 10;

            byte[] buffer = new byte[bufLen];
            int    read   = 0;

            FileStream fs = null;

            try
            {
                string filePath = GetStoragePath(context, Path.Combine(context.CurrentPath, filename));

                fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufLen);

                if (context.Offset > 0)
                {
                    fs.Seek(context.Offset, SeekOrigin.Begin);
                }

                DateTime dtStart;
                TimeSpan ts;
                int      usedMs = 0, predictMs = 0;
                int      speed = context.User.MaxDownloadSpeed;

                dtStart = DateTime.Now;

                while ((read = fs.Read(buffer, 0, bufLen)) > 0)
                {
                    stream.Write(buffer, 0, read);

                    if (speed > 0) // if speed <=0, then no speed limitation
                    {
                        ts        = DateTime.Now.Subtract(dtStart);
                        usedMs    = (int)ts.TotalMilliseconds;
                        predictMs = read / speed;

                        if (predictMs > usedMs) //Speed control
                        {
                            Thread.Sleep(predictMs - usedMs);
                        }

                        dtStart = DateTime.Now;
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError("Failed to delete file");
                return(false);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
            }
        }
예제 #34
0
        public override long GetUserRealUsedSpace(FtpContext context, string username)
        {
            string userStorageRoot = context.User.Root;

            return(GetDirectorySize(userStorageRoot));
        }
 public abstract void ClearTempDirectory(FtpContext context);
        protected string GetStoragePath(FtpContext context, string virtualPath)
        {
            if (!virtualPath.StartsWith("/"))
            {
                if (context.CurrentPath != "/")
                    virtualPath = context.CurrentPath + "/" + virtualPath;
                else
                    virtualPath = context.CurrentPath + virtualPath;
            }

            //Windows path
            if (Path.DirectorySeparatorChar == '\\')
            {
                virtualPath = SuperSocket.Ftp.FtpCommon.StringUtil.ReverseSlash(virtualPath, '/');
            }

            return GetStoragePathInternal(context, virtualPath);
        }
 protected virtual string GetStoragePathInternal(FtpContext context, string virtualPath)
 {
     virtualPath = virtualPath.TrimStart(Path.DirectorySeparatorChar);
     return(Path.Combine(context.User.Root, virtualPath));
 }
        public virtual bool DeleteFile(FtpContext context, string filename)
        {
            string filepath = GetStoragePath(context, filename);

            if (File.Exists(filepath))
            {
                FileInfo file = new FileInfo(filepath);

                long fileLength = file.Length;

                try
                {
                    File.Delete(filepath);
                    context.ChangeSpace(0 - fileLength);
                    return true;
                }
                catch (UnauthorizedAccessException uae)
                {
                    AppServer.Logger.Error(uae);
                    context.SetError(FtpCoreResource.PermissionDenied_550);
                    return false;
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.DeleteFailed_450, filename);
                    return false;
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return false;
            }
        }
예제 #39
0
 public override void ClearTempDirectory(FtpContext context)
 {
     //Do nothing
 }
        public virtual bool CreateFolder(FtpContext context, string foldername)
        {
            string dir = GetStoragePath(context, foldername);

            if (Directory.Exists(dir) || File.Exists(dir))
            {
                context.SetError(FtpCoreResource.DirectoryAlreadyExist_550, foldername);
                return false;
            }
            else
            {
                try
                {
                    Directory.CreateDirectory(dir);
                    return true;
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.MakeDirFailed_550, foldername);
                    return false;
                }
            }
        }
        public virtual DateTime GetModifyTime(FtpContext context, string filename)
        {
            string filepath = GetStoragePath(context, filename);

            if (File.Exists(filepath))
            {
                try
                {
                    FileInfo file = new FileInfo(filepath);
                    return file.LastWriteTime;
                }
                catch (Exception e)
                {
                    AppServer.Logger.Error(e);
                    context.SetError(FtpCoreResource.FileUnavailable_550);
                    return DateTime.MinValue;
                }
            }
            else
            {
                context.SetError(FtpCoreResource.NotFound_550);
                return DateTime.MinValue;
            }
        }
        public virtual bool RenameFolder(FtpContext context, string oldPath, string newPath)
        {
            oldPath = GetStoragePath(context, oldPath);
            newPath = GetStoragePath(context, newPath);

            try
            {
                Directory.Move(oldPath, newPath);
                return true;
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError(FtpCoreResource.RenameDirectoryFailed_553);
                return false;
            }
        }
        public void SendResponse(FtpContext context, List<ListItem> list)
        {
            Stream stream = GetStream(context);

            if (list == null || list.Count <= 0)
                return;

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < list.Count; i++)
            {
                sb.Append(list[i].Permission);

                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);

                sb.Append("1");
                sb.Append(DELIM);
                sb.Append("user");
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append(DELIM);
                sb.Append("group");

                sb.Append(DELIM);

                sb.Append(GetFixedLength(list[i].Length));

                sb.Append(DELIM);

                sb.Append(GetListTimeString(list[i].LastModifiedTime));

                sb.Append(DELIM);

                sb.Append(list[i].Name);

                sb.Append(NEWLINE);

                byte[] data = context.Charset.GetBytes(sb.ToString());
                stream.Write(data, 0, data.Length);

                sb.Remove(0, sb.Length);
            }

            stream.Flush();
        }
        public virtual bool ReadFile(FtpContext context, string filename, Stream stream)
        {
            int bufLen = 1024 * 10;
            byte[] buffer = new byte[bufLen];
            int read = 0;

            FileStream fs = null;

            try
            {
                string filePath = GetStoragePath(context, Path.Combine(context.CurrentPath, filename));

                fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufLen);

                if (context.Offset > 0)
                    fs.Seek(context.Offset, SeekOrigin.Begin);

                DateTime dtStart;
                TimeSpan ts;
                int usedMs = 0, predictMs = 0;
                int speed = context.User.MaxDownloadSpeed;

                dtStart = DateTime.Now;

                while ((read = fs.Read(buffer, 0, bufLen)) > 0)
                {
                    stream.Write(buffer, 0, read);

                    if (speed > 0) // if speed <=0, then no speed limitation
                    {
                        ts = DateTime.Now.Subtract(dtStart);
                        usedMs = (int)ts.TotalMilliseconds;
                        predictMs = read / speed;

                        if (predictMs > usedMs) //Speed control
                            Thread.Sleep(predictMs - usedMs);

                        dtStart = DateTime.Now;
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.SetError("Failed to delete file");
                return false;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
            }

        }
        public virtual List<ListItem> GetList(FtpContext context)
        {
            string dir = GetStoragePath(context, context.CurrentPath);

            return GetList(context, dir);
        }
        protected bool StoreFile(FtpContext context, string filename, Stream stream, StoreOption option)
        {
            int bufLen = 1024 * 10;
            byte[] buffer = new byte[bufLen];
            int read = 0;
            long totalRead = 0;

            int speed = context.User.MaxUploadSpeed;

            FileStream fs = null;

            try
            {
                string filePath = GetStoragePath(context, filename);

                if (context.Offset > 0 && option.AppendOriginalFile) //Append
                {
                    FileInfo file = new FileInfo(filePath);

                    if (context.Offset != file.Length)
                    {
                        context.Status = FtpStatus.Error;
                        context.Message = "Invalid offset";
                        return false;
                    }

                    fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Write, bufLen);
                }
                else
                {
                    if (File.Exists(filePath))
                    {
                        FileInfo file = new FileInfo(filePath);
                        var fileLength = file.Length;
                        File.Delete(filePath);
                        context.ChangeSpace(0 - fileLength);
                    }

                    fs = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Write, bufLen);
                }


                DateTime dtStart;
                TimeSpan ts;
                int usedMs = 0, predictMs = 0;

                dtStart = DateTime.Now;

                while ((read = stream.Read(buffer, 0, bufLen)) > 0)
                {
                    fs.Write(buffer, 0, read);
                    totalRead += read;
                    context.ChangeSpace(read);

                    if (speed > 0) // if speed <=0, then no speed limitation
                    {
                        ts = DateTime.Now.Subtract(dtStart);
                        usedMs = (int)ts.TotalMilliseconds;
                        predictMs = read / speed;

                        if (predictMs > usedMs) //Speed control
                        {
                            Thread.Sleep(predictMs - usedMs);
                        }

                        dtStart = DateTime.Now;
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                AppServer.Logger.Error(e);
                context.Status = FtpStatus.Error;
                context.Message = "Store file error";
                return false;
            }
            finally
            {
                option.TotalRead = totalRead;

                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
            }
        }