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
}
}