using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; namespace HslCommunication.Enthernet { /// <summary> /// 文件管理类服务器,负责服务器所有分类文件的管理,特点是不支持文件附加数据,但是支持直接访问文件名 /// </summary> /// <remarks> /// 本文件的服务器不支持存储文件携带的额外信息,是直接将文件存放在服务器指定目录下的,文件名不更改,特点是服务器查看方便。 /// </remarks> /// <example> /// 以下的示例来自Demo项目,创建了一个简单的服务器对象。 /// <code lang="cs" source="TestProject\FileNetServer\FormFileServer.cs" region="Advanced Server" title="AdvancedFileServer示例" /> /// </example> public class AdvancedFileServer : HslCommunication.Core.Net.NetworkFileServerBase { #region Constructor /// <summary> /// 实例化一个对象 /// </summary> public AdvancedFileServer() { } #endregion #region Override Method /// <summary> /// 当接收到了新的请求的时候执行的操作 /// </summary> /// <param name="socket">异步对象</param> /// <param name="endPoint">终结点</param> protected override void ThreadPoolLogin(Socket socket, IPEndPoint endPoint) { OperateResult result = new OperateResult(); // 获取ip地址 string IpAddress = ((IPEndPoint)(socket.RemoteEndPoint)).Address.ToString(); // 接收操作信息 OperateResult infoResult = ReceiveInformationHead( socket, out int customer, out string fileName, out string Factory, out string Group, out string Identify); if (!infoResult.IsSuccess) { Console.WriteLine(infoResult.ToMessageShowString()); return; } string relativeName = ReturnRelativeFileName(Factory, Group, Identify, fileName); // 操作分流 if (customer == HslProtocol.ProtocolFileDownload) { string fullFileName = ReturnAbsoluteFileName(Factory, Group, Identify, fileName); // 发送文件数据 OperateResult sendFile = SendFileAndCheckReceive(socket, fullFileName, fileName, "", ""); if (!sendFile.IsSuccess) { LogNet?.WriteError(ToString(), $"{StringResources.Language.FileDownloadFailed}:{relativeName} ip:{IpAddress} reason:{sendFile.Message}"); return; } else { socket?.Close(); LogNet?.WriteInfo(ToString(), StringResources.Language.FileDownloadSuccess + ":" + relativeName); } } else if (customer == HslProtocol.ProtocolFileUpload) { string tempFileName = FilesDirectoryPathTemp + "\\" + CreateRandomFileName(); string fullFileName = ReturnAbsoluteFileName(Factory, Group, Identify, fileName); // 上传文件 CheckFolderAndCreate(); // 创建新的文件夹 try { FileInfo info = new FileInfo(fullFileName); if (!Directory.Exists(info.DirectoryName)) { Directory.CreateDirectory(info.DirectoryName); } } catch (Exception ex) { LogNet?.WriteException(ToString(), StringResources.Language.FilePathCreateFailed + fullFileName, ex); socket?.Close(); return; } OperateResult receiveFile = ReceiveFileFromSocketAndMoveFile( socket, // 网络套接字 tempFileName, // 临时保存文件路径 fullFileName, // 最终保存文件路径 out string FileName, // 文件名称,从客户端上传到服务器时,为上传人 out long FileSize, out string FileTag, out string FileUpload ); if (receiveFile.IsSuccess) { socket?.Close(); LogNet?.WriteInfo(ToString(), StringResources.Language.FileUploadSuccess + ":" + relativeName); } else { LogNet?.WriteInfo(ToString(), StringResources.Language.FileUploadFailed + ":" + relativeName + " " + StringResources.Language.TextDescription + receiveFile.Message); } } else if (customer == HslProtocol.ProtocolFileDelete) { string fullFileName = ReturnAbsoluteFileName(Factory, Group, Identify, fileName); bool deleteResult = DeleteFileByName(fullFileName); // 回发消息 if (SendStringAndCheckReceive( socket, // 网络套接字 deleteResult ? 1 : 0, // 是否移动成功 deleteResult ? StringResources.Language.FileDeleteSuccess : StringResources.Language.FileDeleteFailed ).IsSuccess) { socket?.Close(); } if (deleteResult) LogNet?.WriteInfo(ToString(), StringResources.Language.FileDeleteSuccess + ":" + relativeName); } else if (customer == HslProtocol.ProtocolFileDirectoryFiles) { List<GroupFileItem> fileNames = new List<GroupFileItem>(); foreach (var m in GetDirectoryFiles(Factory, Group, Identify)) { FileInfo fileInfo = new FileInfo(m); fileNames.Add(new GroupFileItem() { FileName = fileInfo.Name, FileSize = fileInfo.Length, }); } Newtonsoft.Json.Linq.JArray jArray = Newtonsoft.Json.Linq.JArray.FromObject(fileNames.ToArray()); if (SendStringAndCheckReceive( socket, HslProtocol.ProtocolFileDirectoryFiles, jArray.ToString()).IsSuccess) { socket?.Close(); } } else if (customer == HslProtocol.ProtocolFileDirectories) { List<string> folders = new List<string>(); foreach (var m in GetDirectories(Factory, Group, Identify)) { DirectoryInfo directory = new DirectoryInfo(m); folders.Add(directory.Name); } Newtonsoft.Json.Linq.JArray jArray = Newtonsoft.Json.Linq.JArray.FromObject(folders.ToArray()); if (SendStringAndCheckReceive( socket, HslProtocol.ProtocolFileDirectoryFiles, jArray.ToString()).IsSuccess) { socket?.Close(); } } else { socket?.Close(); } } /// <summary> /// 初始化数据 /// </summary> protected override void StartInitialization() { if (string.IsNullOrEmpty(FilesDirectoryPathTemp)) { throw new ArgumentNullException("FilesDirectoryPathTemp", "No saved path is specified"); } base.StartInitialization(); } /// <summary> /// 检查文件夹 /// </summary> protected override void CheckFolderAndCreate() { if (!Directory.Exists(FilesDirectoryPathTemp)) { Directory.CreateDirectory(FilesDirectoryPathTemp); } base.CheckFolderAndCreate(); } /// <summary> /// 从网络套接字接收文件并移动到目标的文件夹中,如果结果异常,则结束通讯 /// </summary> /// <param name="socket"></param> /// <param name="savename"></param> /// <param name="fileNameNew"></param> /// <param name="filename"></param> /// <param name="size"></param> /// <param name="filetag"></param> /// <param name="fileupload"></param> /// <returns></returns> private OperateResult ReceiveFileFromSocketAndMoveFile( Socket socket, string savename, string fileNameNew, out string filename, out long size, out string filetag, out string fileupload ) { // 先接收文件 OperateResult<FileBaseInfo> fileInfo = ReceiveFileFromSocket(socket, savename, null); if (!fileInfo.IsSuccess) { DeleteFileByName(savename); filename = null; size = 0; filetag = null; fileupload = null; return fileInfo; } filename = fileInfo.Content.Name; size = fileInfo.Content.Size; filetag = fileInfo.Content.Tag; fileupload = fileInfo.Content.Upload; // 标记移动文件,失败尝试三次 int customer = 0; int times = 0; while (times < 3) { times++; if (MoveFileToNewFile(savename, fileNameNew)) { customer = 1; break; } else { Thread.Sleep(500); } } if (customer == 0) { DeleteFileByName(savename); } // 回发消息 OperateResult sendString = SendStringAndCheckReceive(socket, customer, "success"); return sendString; } #endregion #region Public Method /// <summary> /// 用于接收上传文件时的临时文件夹,临时文件使用结束后会被删除 /// </summary> public string FilesDirectoryPathTemp { get { return m_FilesDirectoryPathTemp; } set { m_FilesDirectoryPathTemp = PreprocessFolderName(value); } } #endregion #region Private Member private string m_FilesDirectoryPathTemp = null; #endregion #region Object Override /// <summary> /// 获取本对象的字符串标识形式 /// </summary> /// <returns>字符串对象</returns> public override string ToString() { return "AdvancedFileServer"; } #endregion } }