NetworkFileServerBase.cs 12.4 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using HslCommunication.BasicFramework;
using HslCommunication.Enthernet;
using HslCommunication.LogNet;
using System.Threading;

namespace HslCommunication.Core.Net
{
    /// <summary>
    /// 文件服务器类的基类,为直接映射文件模式和间接映射文件模式提供基础的方法支持
    /// </summary>
    public class NetworkFileServerBase : NetworkServerBase
    {
        #region File Mark

        /// <summary>
        /// 所有文件操作的词典锁
        /// </summary>
        internal Dictionary<string, FileMarkId> m_dictionary_files_marks = new Dictionary<string, FileMarkId>( );
        /// <summary>
        /// 词典的锁
        /// </summary>
        private SimpleHybirdLock dict_hybirdLock = new SimpleHybirdLock( );

        /// <summary>
        /// 获取当前文件的读写锁,如果没有会自动创建
        /// </summary>
        /// <param name="filename">完整的文件路径</param>
        /// <returns>读写锁</returns>
        internal FileMarkId GetFileMarksFromDictionaryWithFileName( string filename )
        {
            FileMarkId fileMarkId = null;
            dict_hybirdLock.Enter( );

            // lock operator
            if (m_dictionary_files_marks.ContainsKey( filename ))
            {
                fileMarkId = m_dictionary_files_marks[filename];
            }
            else
            {
                fileMarkId = new FileMarkId( LogNet, filename );
                m_dictionary_files_marks.Add( filename, fileMarkId );
            }

            dict_hybirdLock.Leave( );
            return fileMarkId;
        }

        #endregion

        #region Receie File Head

        /// <summary>
        /// 接收本次操作的信息头数据
        /// </summary>
        /// <param name="socket">网络套接字</param>
        /// <param name="command">命令</param>
        /// <param name="fileName">文件名</param>
        /// <param name="factory">第一大类</param>
        /// <param name="group">第二大类</param>
        /// <param name="id">第三大类</param>
        /// <returns>是否成功的结果对象</returns>
        protected OperateResult ReceiveInformationHead(
            Socket socket,
            out int command,
            out string fileName,
            out string factory,
            out string group,
            out string id
            )
        {
            // 先接收文件名
            OperateResult<int,string> fileNameResult = ReceiveStringContentFromSocket( socket );
            if (!fileNameResult.IsSuccess)
            {
                command = 0;
                fileName = null;
                factory = null;
                group = null;
                id = null;
                return fileNameResult;
            }

            command = fileNameResult.Content1;
            fileName = fileNameResult.Content2;

            // 接收Factory
            OperateResult<int, string> factoryResult = ReceiveStringContentFromSocket( socket );
            if (!factoryResult.IsSuccess)
            {
                factory = null;
                group = null;
                id = null;
                return factoryResult;
            }
            factory = factoryResult.Content2;
            

            // 接收Group
            OperateResult<int, string> groupResult = ReceiveStringContentFromSocket( socket );
            if (!groupResult.IsSuccess)
            {
                group = null;
                id = null;
                return groupResult;
            }
            group = groupResult.Content2;

            // 最后接收id
            OperateResult<int, string> idResult = ReceiveStringContentFromSocket( socket );
            if (!idResult.IsSuccess)
            {
                id = null;
                return idResult;
            }
            id = idResult.Content2;

            return OperateResult.CreateSuccessResult( ) ;
        }

        /// <summary>
        /// 获取一个随机的文件名,由GUID码和随机数字组成
        /// </summary>
        /// <returns>文件名</returns>
        protected string CreateRandomFileName( )
        {
            return BasicFramework.SoftBasic.GetUniqueStringByGuidAndRandom( );
        }

        /// <summary>
        /// 返回服务器的绝对路径
        /// </summary>
        /// <param name="factory">第一大类</param>
        /// <param name="group">第二大类</param>
        /// <param name="id">第三大类</param>
        /// <returns>是否成功的结果对象</returns>
        protected string ReturnAbsoluteFilePath( string factory, string group, string id )
        {
            string result = m_FilesDirectoryPath;
            if (!string.IsNullOrEmpty( factory )) result += "\\" + factory;
            if (!string.IsNullOrEmpty( group )) result += "\\" + group;
            if (!string.IsNullOrEmpty( id )) result += "\\" + id;
            return result;
        }


        /// <summary>
        /// 返回服务器的绝对路径
        /// </summary>
        /// <param name="factory">第一大类</param>
        /// <param name="group">第二大类</param>
        /// <param name="id">第三大类</param>
        /// <param name="fileName">文件名</param>
        /// <returns>是否成功的结果对象</returns>
        protected string ReturnAbsoluteFileName( string factory, string group, string id, string fileName )
        {
            return ReturnAbsoluteFilePath( factory, group, id ) + "\\" + fileName;
        }


        /// <summary>
        /// 返回相对路径的名称
        /// </summary>
        /// <param name="factory">第一大类</param>
        /// <param name="group">第二大类</param>
        /// <param name="id">第三大类</param>
        /// <param name="fileName">文件名</param>
        /// <returns>是否成功的结果对象</returns>
        protected string ReturnRelativeFileName( string factory, string group, string id, string fileName )
        {
            string result = "";
            if (!string.IsNullOrEmpty( factory )) result += factory + "\\";
            if (!string.IsNullOrEmpty( group )) result += group + "\\";
            if (!string.IsNullOrEmpty( id )) result += id + "\\";
            return result + fileName;
        }


        #endregion

        #region Clear File Mark

        //private Timer timer;

        //private void ClearDict(object obj)
        //{
        //    hybirdLock.Enter();

        //    List<string> waitRemove = new List<string>();
        //    foreach(var m in m_dictionary_files_marks)
        //    {
        //        if(m.Value.CanClear())
        //        {
        //            waitRemove.Add(m.Key);
        //        }
        //    }

        //    foreach(var m in waitRemove)
        //    {
        //        m_dictionary_files_marks.Remove(m);
        //    }

        //    waitRemove.Clear();
        //    waitRemove = null;

        //    hybirdLock.Leave();
        //}
        #endregion

        #region 临时文件复制块

        /// <summary>
        /// 移动一个文件到新的文件去
        /// </summary>
        /// <param name="fileNameOld">旧的文件名称</param>
        /// <param name="fileNameNew">新的文件名称</param>
        /// <returns>是否成功</returns>
        protected bool MoveFileToNewFile( string fileNameOld, string fileNameNew )
        {
            try
            {
                FileInfo info = new FileInfo( fileNameNew );
                if (!Directory.Exists( info.DirectoryName ))
                {
                    Directory.CreateDirectory( info.DirectoryName );
                }

                if (File.Exists( fileNameNew ))
                {
                    File.Delete( fileNameNew );
                }

                File.Move( fileNameOld, fileNameNew );
                return true;
            }
            catch (Exception ex)
            {
                LogNet?.WriteException( ToString(), "Move a file to new file failed: ", ex );
                return false;
            }
        }



        /// <summary>
        /// 删除文件并回发确认信息,如果结果异常,则结束通讯
        /// </summary>
        /// <param name="socket">网络套接字</param>
        /// <param name="fullname">完整路径的文件名称</param>
        /// <returns>是否成功的结果对象</returns>
        protected OperateResult DeleteFileAndCheck(
            Socket socket,
            string fullname
            )
        {
            // 删除文件,如果失败,重复三次
            int customer = 0;
            int times = 0;
            while (times < 3)
            {
                times++;
                if (DeleteFileByName( fullname ))
                {
                    customer = 1;
                    break;
                }
                else
                {
                    Thread.Sleep( 500 );
                }
            }

            // 回发消息
           return SendStringAndCheckReceive( socket, customer, StringResources.Language.SuccessText );
        }



        #endregion

        #region File Upload Event

        // 文件的上传事件


        #endregion

        #region Override Method



        /// <summary>
        /// 服务器启动时的操作
        /// </summary>
        protected override void StartInitialization( )
        {
            if (string.IsNullOrEmpty( FilesDirectoryPath ))
            {
                throw new ArgumentNullException( "FilesDirectoryPath", "No saved path is specified" );
            }

            CheckFolderAndCreate( );
            base.StartInitialization( );
        }

        #endregion

        #region Protect Method



        /// <summary>
        /// 检查文件夹是否存在,不存在就创建
        /// </summary>
        protected virtual void CheckFolderAndCreate( )
        {
            if (!Directory.Exists( FilesDirectoryPath ))
            {
                Directory.CreateDirectory( FilesDirectoryPath );
            }
        }

        #endregion

        #region Public Members

        /// <summary>
        /// 文件所存储的路径
        /// </summary>
        public string FilesDirectoryPath
        {
            get { return m_FilesDirectoryPath; }
            set { m_FilesDirectoryPath = PreprocessFolderName( value ); }
        }


        /// <summary>
        /// 获取文件夹的所有文件列表
        /// </summary>
        /// <param name="factory">第一大类</param>
        /// <param name="group">第二大类</param>
        /// <param name="id">第三大类</param>
        /// <returns>文件列表</returns>
        public virtual string[] GetDirectoryFiles( string factory, string group, string id )
        {
            if (string.IsNullOrEmpty( FilesDirectoryPath )) return new string[0];

            string absolutePath = ReturnAbsoluteFilePath( factory, group, id );

            // 如果文件夹不存在
            if (!Directory.Exists( absolutePath )) return new string[0];
            // 返回文件列表
            return Directory.GetFiles( absolutePath );
        }

        /// <summary>
        /// 获取文件夹的所有文件夹列表
        /// </summary>
        /// <param name="factory">第一大类</param>
        /// <param name="group">第二大类</param>
        /// <param name="id">第三大类</param>
        /// <returns>文件夹列表</returns>
        public string[] GetDirectories( string factory, string group, string id )
        {
            if (string.IsNullOrEmpty( FilesDirectoryPath )) return new string[0];

            string absolutePath = ReturnAbsoluteFilePath( factory, group, id );

            // 如果文件夹不存在
            if (!Directory.Exists( absolutePath )) return new string[0];
            // 返回文件列表
            return Directory.GetDirectories( absolutePath );
        }

        #endregion

        #region Private Members

        private string m_FilesDirectoryPath = null;      // 文件的存储路径
        private Random m_random = new Random( );          // 随机生成的文件名

        #endregion

        #region Object Override

        /// <summary>
        /// 获取本对象的字符串标识形式
        /// </summary>
        /// <returns>对象信息</returns>
        public override string ToString( )
        {
            return "NetworkFileServerBase";
        }

        #endregion
    }
}