/// <summary>
        /// Download a file
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public RemoteFileDescriptor Download(RemoteFileIdentifier request)
        {
            //Get path to file storage
            string sPath = FileStorage.Provider.ConnectionString;

            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(sPath);

            //Get the file guid
            string sFileGuid = System.IO.Path.GetFileNameWithoutExtension(request.RemoteFile.LocalPath);
            Guid   gFileGuid = new Guid(sFileGuid);

            //Get file definition
            File f = FileBroker.SelectByGuid(gFileGuid, di);

            System.Diagnostics.Debug.Assert(f.Guid == gFileGuid);

            //Report start
            System.Diagnostics.Trace.WriteLine("Start downloading " + f.FileName);

            //Open stream
            _StorageStream = FileStorage.GetFileStream(f.Key, AccessMode.Read);
            System.Diagnostics.Debug.Assert(f.Size == _StorageStream.Length);

            //Note that we cannot close the stream before returning the stream to the client
            //Otherwise the client gets a closed stream.
            //So we need to monitor the use of the stream made by the client to close it on a separate thread
            //once the client has entirely read it or once the connection is closed
            //System.Threading.Thread objMonitoringThread = new System.Threading.Thread(
            //    new System.Threading.ParameterizedThreadStart(this.MonitorAndClose));
            //objMonitoringThread.Start(objStorageStream);

            RemoteFileDescriptor objRemoteFileInfoRet = new RemoteFileDescriptor();

            objRemoteFileInfoRet.ContentType  = f.ContentType;
            objRemoteFileInfoRet.Email        = null;
            objRemoteFileInfoRet.FileGuid     = f.Guid;
            objRemoteFileInfoRet.FileName     = f.FileName;
            objRemoteFileInfoRet.HashCode     = f.HashValue;
            objRemoteFileInfoRet.Length       = f.Size;
            objRemoteFileInfoRet.SecurityCode = null;
            objRemoteFileInfoRet.Stream       = _StorageStream;

            // report end
            System.Diagnostics.Trace.WriteLine("Download complete!");

            // return result
            return(objRemoteFileInfoRet);
        }
        /// <summary>
        /// Upload a file
        /// </summary>
        /// <param name="request"></param>
        public void Upload(RemoteFileDescriptor request)
        {
            //report start
            System.Diagnostics.Trace.WriteLine("Start uploading " + request.FileName);

            //TODO: We need to report exceptions properly using FaultContractAttribute and FaultException
            //In this particular example, we want to raise a proper exception as soon as possible if the file upload is too large.
            //Note that currently the upload progresses for a while before the exception is raised.

            //Using HttpContext to access configuration data (especially httpRuntime section in web.config)
            //from WCF services requires HttpContext which is only available to WCF services in Asp.Net compatibility mode
            //See: http://blogs.msdn.com/wenlong/archive/2006/01/23/516041.aspx

            //But the good news is apparently since .NET 3.0 SP1, WCF services are not dependant upon the httpRuntime section
            //See: http://blogs.msdn.com/wenlong/archive/2008/03/10/why-changing-sendtimeout-does-not-help-for-hosted-wcf-services.aspx
            //So we essentially need to check that request.Length (unless there is a way to access the Content-Length Htpp header)
            //is lower than the value of BasicHttpBinding.MaxReceivedMessageSize configured in web.config

#if NOTUSED
            //Raise error Http 413 asap
            //Use FaultContractAttribute and FaultException to report an error
            Binding objBinding = OperationContext.Current.Host.Description.Endpoints[0].Binding;
            System.Diagnostics.Debug.Assert(objBinding.Name == "BasicHttpBinding");
            BasicHttpBinding objBasicHttpBinding = objBinding as BasicHttpBinding;
            if (objBasicHttpBinding != null)
            {
                if (request.Length > objBasicHttpBinding.MaxReceivedMessageSize)
                {
                    throw new System.Web.HttpException(413, "Too large!");
                }
            }
#endif

            //Authenticate user
            if (!Authenticate(request.Email, request.SecurityCode))
            {
                throw new ApplicationException(Resources.Web.glossary.WebService_AuthenticationFailInfo);
            }

            //Stream file
            int    iBytesRead;
            byte[] arrBuffer = new byte[Constants.WcfStreamingBufferSize];

            //The file key is unknown from the client
            object objProviderFileKey = FileStorage.GetNewFileKey(request.FileName);

            //Create stream to write to
            _StorageStream = FileStorage.GetFileStream(objProviderFileKey, AccessMode.Create);
            do
            {
                // Read bytes from input stream
                iBytesRead = request.Stream.Read(arrBuffer, 0, Constants.WcfStreamingBufferSize);
                // Write bytes to output stream
                _StorageStream.Write(arrBuffer, 0, iBytesRead);
            } while (iBytesRead > 0);
            _StorageStream.Close();

            //Create file object
            File f = new File(
                request.FileGuid,
                request.FileName,
                request.ContentType,
                objProviderFileKey.ToString(),
                request.Length,
                request.HashCode);

            //Get path to file storage
            string sPath = FileStorage.Provider.ConnectionString;
            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(sPath);

            //Add definition to file storage (Existence will be checked in FileBroker)
            FileBroker.Insert(f, di);

            // report end
            System.Diagnostics.Trace.WriteLine("Upload complete!");
        }