/// <summary>
        /// Upload a file chunk
        /// </summary>
        /// <param name="logonId">Logon id of user</param>
        /// <param name="TransferId">Transfer id</param>
        /// <param name="FilePosition">Position of start of data chunk</param>
        /// <param name="ChunkSize">Size of chunk</param>
        /// <param name="Bytes">Bytes in chunk</param>
        public static void UploadChunk(Guid logonId, Guid TransferId, long FilePosition, int ChunkSize, byte[] Bytes)
        {
            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            if (!FileTransferData.IsUpload)
            {
                throw new Exception("File upload has not been started");
            }

            if (FileTransferData.TransferId != TransferId)
            {
                throw new Exception("Transfer id does not match");
            }

            if (FileTransferData.FileStream == null)
            {
                throw new Exception("File upload has not been started or has timed out");
            }

            if (FileTransferData.FileStream.Position != FilePosition)
            {
                throw new Exception("File pointer is in the wrong position");
            }

            FileTransferData.FileStream.Write(Bytes, 0, ChunkSize);
        }
        /// <summary>
        /// Download a chunk of data
        /// </summary>
        /// <param name="logonId">Logon id of user</param>
        /// <param name="TransferId">Transfer id</param>
        /// <param name="StreamPosition">The start position of the data chunk</param>
        /// <returns></returns>
        public static FileChunkData DownloadChunk(Guid logonId, Guid TransferId, long StreamPosition)
        {
            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            if (!FileTransferData.IsDownload)
            {
                throw new Exception("File download has not been started");
            }

            if (FileTransferData.TransferId != TransferId)
            {
                throw new Exception("Transfer id does not match");
            }

            if (FileTransferData.FileStream == null)
            {
                throw new Exception("File download has not been started or has timed out");
            }

            if (FileTransferData.FileStream.Position != StreamPosition)
            {
                FileTransferData.FileStream.Seek(StreamPosition, SeekOrigin.Begin);
            }

            FileChunkData FileChunkData = new FileChunkData();

            FileChunkData.Bytes     = new byte[Host.FileTransferChunkSize];
            FileChunkData.ChunkSize = FileTransferData.FileStream.Read(FileChunkData.Bytes,
                                                                       0, Host.FileTransferChunkSize);

            return(FileChunkData);
        }
        /// <summary>
        /// Start a file upload
        /// </summary>
        /// <param name="logonId">Logon id of user</param>
        /// <param name="FileName">File name without path</param>
        /// <param name="ModifiedDate">Modified date of file</param>
        /// <param name="Size">Size of file</param>
        /// <param name="Hash">Hash of file</param>
        /// <returns></returns>
        public static Guid StartFileUpload(Guid logonId, string FileName, DateTime ModifiedDate, long Size, byte[] Hash, object AssociatedData)
        {
            if (FileName.Contains(Path.DirectorySeparatorChar))
            {
                throw new Exception("Upload file name must not include the path part");
            }

            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            FileTransferData.TransferId = Guid.NewGuid();
            FileTransferData.IsUpload   = true;

            //FileTransferData.TempFileName = Path.GetTempFileName();
            // This is been changed, because the file which is being uploaded should have same extension for the temp file also
            FileTransferData.TempFileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + Path.GetExtension(FileName));

            FileTransferData.FileName       = FileName;
            FileTransferData.ModifiedDate   = ModifiedDate;
            FileTransferData.Size           = Size;
            FileTransferData.Hash           = Hash;
            FileTransferData.AssociatedData = AssociatedData;

            FileTransferData.FileStream = new FileStream(
                FileTransferData.TempFileName, FileMode.Create, FileAccess.Write, FileShare.Read);

            return(FileTransferData.TransferId);
        }
        /// <summary>
        /// Call this when the download is complete to reset the cache
        /// </summary>
        /// <param name="logonId"></param>
        /// <param name="TransferId"></param>
        public static void DownloadComplete(Guid logonId, Guid TransferId)
        {
            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            if (FileTransferData.TransferId != TransferId)
            {
                throw new Exception("Transfer id does not match");
            }

            FileTransferData.Reset();
        }
        /// <summary>
        /// Call this to say that the upload is complete.
        /// The returned FileUploadInfo.TempFileName gives you the actual file that has been uploaded.
        /// FileUploadInfo.FileName tells you what that file should be called (was originally called on the client).
        /// You should call UploadReset() when you have finished with the temp file.
        /// </summary>
        /// <param name="logonId">Logon id of user</param>
        /// <param name="TransferId">Transfer id</param>
        /// <returns></returns>
        public static FileUploadInfo UploadComplete(Guid logonId, Guid TransferId)
        {
            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            if (!FileTransferData.IsUpload)
            {
                throw new Exception("File upload has not been started");
            }

            if (FileTransferData.TransferId != TransferId)
            {
                throw new Exception("Transfer id does not match");
            }

            if (FileTransferData.FileStream == null)
            {
                throw new Exception("File upload has not been started or has timed out");
            }

            FileTransferData.FileStream.Close();

            FileUploadInfo FileUploadInfo = new FileUploadInfo();

            try
            {
                if (new FileInfo(FileTransferData.TempFileName).Length != FileTransferData.Size)
                {
                    throw new Exception("File upload failed, file size is wrong");
                }

                byte[] LocalHash = FileTransferHash.CreateFileMD5Hash(FileTransferData.TempFileName);

                if (!FileTransferHash.CheckHash(LocalHash, FileTransferData.Hash))
                {
                    throw new Exception("File upload failed, checksum does not match");
                }

                File.SetLastWriteTime(FileTransferData.TempFileName, FileTransferData.ModifiedDate);

                FileUploadInfo.TempFileName = FileTransferData.TempFileName;
                FileUploadInfo.FileName     = FileTransferData.FileName;
                FileUploadInfo.ModifiedDate = FileTransferData.ModifiedDate;
                FileUploadInfo.Size         = FileTransferData.Size;
            }
            catch
            {
                FileTransferData.Reset();
                throw;
            }

            return(FileUploadInfo);
        }
        /// <summary>
        /// Start the file download
        /// </summary>
        /// <param name="logonId">Logon id of user</param>
        /// <param name="FileName">Source file to be downloaded</param>
        /// <param name="FileIsTemp">If the source file to be downloaded is a temp file set this to true so that
        /// it will automatically be deleted at the end.
        /// e.g. if you have extratced a file from an archive into a temp file for download then set this
        /// to true</param>
        /// <returns></returns>
        public static FileDownloadInfo StartFileDownload(Guid logonId, string SourceFileName, bool FileIsTemp)
        {
            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            FileTransferData.TransferId = Guid.NewGuid();
            FileTransferData.IsDownload = true;

            FileTransferData.FileName = SourceFileName;

            if (FileIsTemp)
            {
                FileTransferData.TempFileName = SourceFileName;
            }
            else
            {
                FileTransferData.TempFileName = null;
            }

            FileDownloadInfo FileDownloadInfo = new FileDownloadInfo();

            FileTransferData.FileStream = new FileStream(SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);

            try
            {
                FileInfo FInfo = new FileInfo(SourceFileName);

                FileTransferData.ModifiedDate = FInfo.LastWriteTime;
                FileTransferData.Size         = FInfo.Length;

                FileDownloadInfo.TransferId = FileTransferData.TransferId;
                // Only return the filename without the path as this is irrelavent to the client
                FileDownloadInfo.FileName     = Path.GetFileName(SourceFileName);
                FileDownloadInfo.ModifiedDate = FInfo.LastWriteTime;
                FileDownloadInfo.Size         = FInfo.Length;
                FileDownloadInfo.Hash         = FileTransferHash.CreateStreamMD5Hash(FileTransferData.FileStream);
                FileTransferData.FileStream.Seek(0, SeekOrigin.Begin);
            }
            catch
            {
                FileTransferData.Reset();
                throw;
            }

            return(FileDownloadInfo);
        }
        /// <summary>
        /// Call this to reset the upload cache.  This will delete the temp file if you have not moved it somewhere.
        /// </summary>
        /// <param name="logonId"></param>
        /// <param name="TransferId"></param>
        public static void UploadReset(Guid logonId, Guid TransferId)
        {
            FileTransferData FileTransferData = Host.GetFileTransferData(logonId);

            if (!FileTransferData.IsUpload)
            {
                throw new Exception("File upload has not been started");
            }

            if (FileTransferData.TransferId != TransferId)
            {
                throw new Exception("Transfer id does not match");
            }

            FileTransferData.Reset();

            // Clear any associated data
            FileTransferData.AssociatedData = null;
        }