替换RRQMSocket.FileTransfer代码

This commit is contained in:
若汝棋茗
2021-08-13 15:27:06 +08:00
parent 21fe3f5fd0
commit 1617271bd2
26 changed files with 1610 additions and 1415 deletions

View File

@@ -1,134 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在RRQMCore.XREF命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.ByteManager;
using RRQMCore.Serialization;
using System;
using System.IO;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件工具类
/// </summary>
public static class FileBaseTool
{
#region Methods
internal static void SaveProgressBlockCollection(RRQMStream stream, ProgressBlockCollection blocks)
{
if (stream.RRQMFileStream != null && stream.RRQMFileStream.CanWrite)
{
stream.RRQMFileStream.Position = 0;
byte[] dataBuffer = SerializeConvert.RRQMBinarySerialize(PBCollectionTemp.GetFromProgressBlockCollection(blocks), true);
stream.RRQMFileStream.Write(dataBuffer, 0, dataBuffer.Length);
stream.RRQMFileStream.Flush();
}
}
internal static bool WriteFile(RRQMStream stream, out string mes, long streamPosition, byte[] buffer, int offset, int length)
{
try
{
if (stream != null && stream.TempFileStream.CanWrite)
{
stream.TempFileStream.Position = streamPosition;
stream.TempFileStream.Write(buffer, offset, length);
stream.TempFileStream.Flush();
mes = null;
return true;
}
mes = "流不可写";
return false;
}
catch (Exception ex)
{
mes = ex.Message;
return false;
}
}
private static int blockCount = 100;
/// <summary>
/// 分块数量
/// </summary>
public static int BlockCount
{
get { return blockCount; }
set
{
if (value < 10)
{
value = 10;
}
blockCount = value;
}
}
internal static ProgressBlockCollection GetProgressBlockCollection(UrlFileInfo urlFileInfo, bool breakpointResume)
{
ProgressBlockCollection blocks = new ProgressBlockCollection();
blocks.UrlFileInfo = urlFileInfo;
long position = 0;
if (breakpointResume && urlFileInfo.FileLength >= blockCount)
{
long blockLength = (long)(urlFileInfo.FileLength / (blockCount * 1.0));
for (int i = 0; i < blockCount; i++)
{
FileProgressBlock block = new FileProgressBlock();
block.Index = i;
block.FileHash = urlFileInfo.FileHash;
block.Finished = false;
block.StreamPosition = position;
block.UnitLength = i != (blockCount - 1) ? blockLength : urlFileInfo.FileLength - i * blockLength;
blocks.Add(block);
position += blockLength;
}
}
else
{
FileProgressBlock block = new FileProgressBlock();
block.Index = 0;
block.FileHash = urlFileInfo.FileHash;
block.Finished = false;
block.StreamPosition = position;
block.UnitLength = urlFileInfo.FileLength;
blocks.Add(block);
}
return blocks;
}
internal static bool ReadFileBytes(string path, long beginPosition, ByteBlock byteBlock, int offset, int length)
{
FileStream fileStream = TransferFileStreamDic.GetFileStream(path);
fileStream.Position = beginPosition;
if (byteBlock.Buffer.Length < length + offset)
{
byteBlock.SetBuffer(new byte[length + offset]);
}
int r = fileStream.Read(byteBlock.Buffer, offset, length);
if (r == length)
{
byteBlock.Position = offset + length;
byteBlock.SetLength(offset + length);
return true;
}
return false;
}
#endregion Methods
}
}

View File

@@ -25,11 +25,16 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 文件流位置
/// </summary>
public long StreamPosition { get; internal set; }
public long Position { get; internal set; }
/// <summary>
/// 文件哈希值
/// 文件块长度
/// </summary>
public string FileHash { get; internal set; }
public long UnitLength { get; internal set; }
/// <summary>
/// 请求状态
/// </summary>
public RequestStatus RequestStatus { get; internal set; }
}
}

View File

@@ -0,0 +1,80 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在RRQMCore.XREF命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.IO;
using System.IO;
using System.Security.Cryptography;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件Hash校验
/// </summary>
public static class FileHashGenerator
{
private static FileHashType fileCheckType;
/// <summary>
/// 文件
/// </summary>
public static FileHashType FileCheckType
{
get { return fileCheckType; }
set { fileCheckType = value; }
}
/// <summary>
/// 获取文件Hash
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string GetFileHash(string path)
{
using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
return GetFileHash(fileStream);
}
}
/// <summary>
/// 获取文件Hash
/// </summary>
/// <param name="fileStream"></param>
/// <returns></returns>
public static string GetFileHash(FileStream fileStream)
{
HashAlgorithm hash;
switch (fileCheckType)
{
case FileHashType.MD5:
hash = MD5.Create();
break;
case FileHashType.SHA1:
hash = SHA1.Create();
break;
case FileHashType.SHA256:
hash = SHA256.Create();
break;
case FileHashType.SHA512:
hash = SHA512.Create();
break;
default:
hash = null;
break;
}
return FileControler.GetStreamHash(fileStream, hash);
}
}
}

View File

@@ -1,57 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在RRQMCore.XREF命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件信息基类
/// </summary>
public class FileInfo
{
/// <summary>
/// 文件名
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public long FileLength { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 文件哈希值
/// </summary>
public string FileHash { get; set; }
/// <summary>
/// 文件标志
/// </summary>
public string Flag { get; set; }
/// <summary>
/// 复制
/// </summary>
/// <param name="fileInfo"></param>
public void Copy(FileInfo fileInfo)
{
this.FileHash = fileInfo.FileHash;
this.FileLength = fileInfo.FileLength;
this.FileName = fileInfo.FileName;
this.FilePath = fileInfo.FilePath;
}
}
}

View File

@@ -0,0 +1,250 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在RRQMCore.XREF命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.ByteManager;
using RRQMCore.Exceptions;
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件流池
/// </summary>
public static class FileStreamPool
{
internal static ConcurrentDictionary<string, RRQMStream> pathStream = new ConcurrentDictionary<string, RRQMStream>();
private readonly static object locker = new object();
private static ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();
internal static bool CheckAllFileBlockFinished(string path)
{
lock (locker)
{
RRQMStream stream;
if (!pathStream.TryGetValue(path, out stream))
{
return false;
}
if (stream.StreamType == StreamOperationType.Read)
{
return false;
}
foreach (var block in stream.Blocks)
{
if (block.RequestStatus != RequestStatus.Finished)
{
return false;
}
}
return true;
}
}
internal static void DisposeReadStream(string path)
{
RRQMStream stream;
if (pathStream.TryGetValue(path, out stream))
{
if (Interlocked.Decrement(ref stream.reference) == 0)
{
if (pathStream.TryRemove(path, out stream))
{
stream.Dispose();
}
}
}
}
internal static void DisposeWriteStream(string path, bool finished)
{
RRQMStream stream;
if (pathStream.TryGetValue(path, out stream))
{
if (Interlocked.Decrement(ref stream.reference) == 0)
{
if (pathStream.TryRemove(path, out stream))
{
if (finished)
{
stream.FinishStream();
}
else
{
stream.Dispose();
}
}
}
}
}
internal static bool GetFreeFileBlock(string path, out FileBlock fileBlock, out string mes)
{
lock (locker)
{
RRQMStream stream;
if (!pathStream.TryGetValue(path, out stream))
{
mes = "没有此路径的写入信息";
fileBlock = null;
return false;
}
if (stream.StreamType == StreamOperationType.Read)
{
mes = "该路径的流为只读";
fileBlock = null;
return false;
}
foreach (var block in stream.Blocks)
{
if (block.RequestStatus == RequestStatus.Hovering)
{
block.RequestStatus = RequestStatus.InProgress;
fileBlock = block;
mes = null;
return true;
}
}
fileBlock = null;
mes = null;
return true;
}
}
internal static bool LoadReadStream(ref UrlFileInfo urlFileInfo, out string mes)
{
RRQMStream stream;
if (pathStream.TryGetValue(urlFileInfo.FilePath, out stream))
{
Interlocked.Increment(ref stream.reference);
mes = null;
return true;
}
else
{
if (RRQMStream.CreateReadStream(out stream, ref urlFileInfo, out mes))
{
Interlocked.Increment(ref stream.reference);
pathStream.TryAdd(urlFileInfo.FilePath, stream);
return true;
}
else
{
return false;
}
}
}
internal static bool LoadWriteStream(ref ProgressBlockCollection blocks, bool onlySearch, out string mes)
{
RRQMStream stream;
string rrqmPath = blocks.UrlFileInfo.SaveFullPath + ".rrqm";
if (!pathStream.TryGetValue(rrqmPath, out stream))
{
if (RRQMStream.CreateWriteStream(out stream, ref blocks, out mes))
{
Interlocked.Increment(ref stream.reference);
mes = null;
return pathStream.TryAdd(rrqmPath, stream);
}
else
{
return false;
}
}
else
{
if (onlySearch)
{
blocks = stream.Blocks;
mes = null;
return true;
}
mes = "该文件流正在被其他客户端拥有";
return false;
}
}
internal static bool ReadFile(string path, out string mes, long beginPosition, ByteBlock byteBlock, int offset, int length)
{
lockSlim.EnterReadLock();
try
{
if (pathStream.TryGetValue(path, out RRQMStream stream))
{
stream.FileStream.Position = beginPosition;
if (byteBlock.Buffer.Length < length + offset)
{
byteBlock.SetBuffer(new byte[length + offset]);
}
int r = stream.FileStream.Read(byteBlock.Buffer, offset, length);
if (r == length)
{
byteBlock.Position = offset + length;
byteBlock.SetLength(offset + length);
mes = null;
return true;
}
}
mes = "没有找到该路径下的流文件";
return false;
}
catch (Exception ex)
{
mes = ex.Message;
return false;
}
finally
{
lockSlim.ExitReadLock();
}
}
internal static void SaveProgressBlockCollection(string path)
{
RRQMStream stream;
if (pathStream.TryGetValue(path, out stream))
{
stream.SaveProgressBlockCollection();
}
else
{
throw new RRQMException("没有找到该路径下的流文件");
}
}
internal static bool WriteFile(string path, out string mes, out RRQMStream stream, long streamPosition, byte[] buffer, int offset, int length)
{
try
{
if (pathStream.TryGetValue(path, out stream))
{
stream.FileStream.Position = streamPosition;
stream.FileStream.Write(buffer, offset, length);
stream.FileStream.Flush();
mes = null;
return true;
}
mes = "未找到该路径下的流";
return false;
}
catch (Exception ex)
{
mes = ex.Message;
stream = null;
return false;
}
}
}
}

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在RRQMCore.XREF命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.Exceptions;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件传输错误码映射
/// </summary>
public class FileTransferErrorExceptionMapping : ErrorExceptionMapping
{
private static FileTransferErrorExceptionMapping _instance = new FileTransferErrorExceptionMapping();
/// <summary>
/// 默认实例
/// </summary>
public static FileTransferErrorExceptionMapping Default { get => _instance; }
}
}

View File

@@ -26,7 +26,7 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 块集合
/// </summary>
public List<FileProgressBlock> Blocks { get; internal set; }
public List<FileBlock> Blocks { get; internal set; }
/// <summary>
/// 从文件块转换
@@ -41,7 +41,7 @@ namespace RRQMSocket.FileTransfer
}
PBCollectionTemp collectionTemp = new PBCollectionTemp();
collectionTemp.UrlFileInfo = progressBlocks.UrlFileInfo;
collectionTemp.Blocks = new List<FileProgressBlock>();
collectionTemp.Blocks = new List<FileBlock>();
collectionTemp.Blocks.AddRange(progressBlocks);
return collectionTemp;
}

View File

@@ -18,13 +18,31 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 文件进度块集合
/// </summary>
public class ProgressBlockCollection : ReadOnlyList<FileProgressBlock>
public class ProgressBlockCollection : ReadOnlyList<FileBlock>
{
/// <summary>
/// 文件信息
/// </summary>
public UrlFileInfo UrlFileInfo { get; internal set; }
private static int blockLength = 1024 * 1024 * 10;
/// <summary>
/// 分块长度,min=1024*1024*5
/// </summary>
public static int BlockLength
{
get { return blockLength; }
set
{
if (value < 1024 * 1024 * 5)
{
value = 1024 * 1024 * 5;
}
blockLength = value;
}
}
/// <summary>
/// 保存
/// </summary>
@@ -63,5 +81,26 @@ namespace RRQMSocket.FileTransfer
return null;
}
}
internal static ProgressBlockCollection CreateProgressBlockCollection(UrlFileInfo urlFileInfo)
{
ProgressBlockCollection blocks = new ProgressBlockCollection();
blocks.UrlFileInfo = urlFileInfo;
long position = 0;
long surLength = urlFileInfo.FileLength;
int index = 0;
while (surLength > 0)
{
FileBlock block = new FileBlock();
block.Index = index++;
block.RequestStatus = RequestStatus.Hovering;
block.Position = position;
block.UnitLength = surLength > blockLength ? blockLength : surLength;
blocks.Add(block);
position += block.UnitLength;
surLength -= block.UnitLength;
}
return blocks;
}
}
}

View File

@@ -11,115 +11,147 @@
//------------------------------------------------------------------------------
using RRQMCore.Serialization;
using System;
using System.Collections.Concurrent;
using System.IO;
namespace RRQMSocket.FileTransfer
{
internal class RRQMStream : IDisposable
internal class RRQMStream
{
internal static ConcurrentDictionary<string, RRQMStream> pathAndStream = new ConcurrentDictionary<string, RRQMStream>();
internal static RRQMStream GetRRQMStream(ref ProgressBlockCollection blocks, bool restart, bool breakpoint)
{
string rrqmPath = blocks.UrlFileInfo.FilePath + ".rrqm";
string tempPath = blocks.UrlFileInfo.FilePath + ".temp";
if (pathAndStream.TryRemove(blocks.UrlFileInfo.FilePath, out RRQMStream rrqmStream))
{
rrqmStream.Dispose();
}
RRQMStream stream = new RRQMStream();
pathAndStream.TryAdd(blocks.UrlFileInfo.FilePath, stream);
stream.fileInfo = blocks.UrlFileInfo;
if (File.Exists(rrqmPath) && File.Exists(tempPath) && !restart && breakpoint)
{
PBCollectionTemp readBlocks = SerializeConvert.RRQMBinaryDeserialize<PBCollectionTemp>(File.ReadAllBytes(rrqmPath));
if (readBlocks.UrlFileInfo != null && blocks.UrlFileInfo != null)
{
if (readBlocks.UrlFileInfo.FileHash != null && blocks.UrlFileInfo.FileHash != null && readBlocks.UrlFileInfo.FileHash == blocks.UrlFileInfo.FileHash)
{
stream.tempFileStream = new FileStream(tempPath, FileMode.Open, FileAccess.ReadWrite);
stream.rrqmFileStream = new FileStream(rrqmPath, FileMode.Open, FileAccess.ReadWrite);
stream.blocks = blocks = readBlocks.ToPBCollection();
return stream;
}
}
}
if (File.Exists(rrqmPath))
{
File.Delete(rrqmPath);
}
if (File.Exists(tempPath))
{
File.Delete(tempPath);
}
if (breakpoint)
{
byte[] dataBuffer = SerializeConvert.RRQMBinarySerialize(PBCollectionTemp.GetFromProgressBlockCollection(blocks), true);
stream.rrqmFileStream = new FileStream(rrqmPath, FileMode.Create, FileAccess.ReadWrite);
stream.rrqmFileStream.Write(dataBuffer, 0, dataBuffer.Length);
stream.rrqmFileStream.Flush();
}
stream.tempFileStream = new FileStream(tempPath, FileMode.Create, FileAccess.ReadWrite);
return stream;
}
internal static void FileFinished(RRQMStream stream)
{
stream.Dispose();
string path = stream.fileInfo.FilePath;
if (File.Exists(path + ".rrqm"))
{
File.Delete(path + ".rrqm");
}
if (File.Exists(path))
{
File.Delete(path);
}
if (File.Exists(path + ".temp"))
{
File.Move(path + ".temp", path);
}
}
internal int reference;
private ProgressBlockCollection blocks;
internal FileInfo fileInfo;
private FileStream fileStream;
private string rrqmPath;
private StreamOperationType streamType;
private FileStream rrqmFileStream;
private UrlFileInfo urlFileInfo;
public FileStream RRQMFileStream
private RRQMStream()
{
get { return rrqmFileStream; }
}
private FileStream tempFileStream;
public ProgressBlockCollection Blocks { get { return blocks; } }
public FileStream TempFileStream
public FileStream FileStream
{
get { return tempFileStream; }
get { return fileStream; }
}
public void Dispose()
public StreamOperationType StreamType
{
get { return streamType; }
}
public UrlFileInfo UrlFileInfo { get => urlFileInfo; }
internal static bool CreateReadStream(out RRQMStream stream, ref UrlFileInfo urlFileInfo, out string mes)
{
stream = new RRQMStream();
try
{
stream.streamType = StreamOperationType.Read;
stream.fileStream = File.OpenRead(urlFileInfo.FilePath);
urlFileInfo.FileLength = stream.fileStream.Length;
stream.urlFileInfo = urlFileInfo;
mes = null;
return true;
}
catch (Exception ex)
{
stream.Dispose();
stream = null;
mes = ex.Message;
return false;
}
}
internal static bool CreateWriteStream(out RRQMStream stream, ref ProgressBlockCollection blocks, out string mes)
{
stream = new RRQMStream();
stream.rrqmPath = blocks.UrlFileInfo.SaveFullPath + ".rrqm";
stream.urlFileInfo = blocks.UrlFileInfo;
stream.streamType = StreamOperationType.Write;
try
{
if (blocks.UrlFileInfo.Flags.HasFlag(TransferFlags.BreakpointResume) && File.Exists(stream.rrqmPath))
{
stream.fileStream = new FileStream(stream.rrqmPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
int blocksLength = (int)(stream.fileStream.Length - blocks.UrlFileInfo.FileLength);
if (blocksLength > 0)
{
stream.fileStream.Position = blocks.UrlFileInfo.FileLength;
byte[] buffer = new byte[blocksLength];
stream.fileStream.Read(buffer, 0, buffer.Length);
try
{
PBCollectionTemp readBlocks = SerializeConvert.RRQMBinaryDeserialize<PBCollectionTemp>(buffer);
if (readBlocks.UrlFileInfo != null && blocks.UrlFileInfo != null && readBlocks.UrlFileInfo.FileHash != null)
{
if (readBlocks.UrlFileInfo.FileHash == blocks.UrlFileInfo.FileHash)
{
stream.blocks = blocks = readBlocks.ToPBCollection();
mes = null;
return true;
}
}
}
catch
{
}
}
stream.fileStream.Dispose();
}
stream.blocks = blocks;
if (File.Exists(stream.rrqmPath))
{
File.Delete(stream.rrqmPath);
}
stream.fileStream = new FileStream(stream.rrqmPath, FileMode.Create, FileAccess.ReadWrite);
stream.SaveProgressBlockCollection();
mes = null;
return true;
}
catch (Exception ex)
{
mes = ex.Message;
stream.Dispose();
stream = null;
return false;
}
}
internal bool FinishStream()
{
this.fileStream.SetLength(this.urlFileInfo.FileLength);
this.fileStream.Flush();
UrlFileInfo info = this.urlFileInfo;
this.Dispose();
if (File.Exists(info.SaveFullPath))
{
File.Delete(info.SaveFullPath);
}
File.Move(info.SaveFullPath + ".rrqm", info.SaveFullPath);
return true;
}
internal void Dispose()
{
string path = this.fileInfo.FilePath;
pathAndStream.TryRemove(path, out _);
this.blocks = null;
if (this.rrqmFileStream != null)
this.urlFileInfo = null;
if (this.fileStream != null)
{
this.rrqmFileStream.Dispose();
this.rrqmFileStream = null;
}
if (this.tempFileStream != null)
{
this.tempFileStream.Dispose();
this.tempFileStream = null;
this.fileStream.Dispose();
this.fileStream = null;
}
}
internal void SaveProgressBlockCollection()
{
byte[] dataBuffer = SerializeConvert.RRQMBinarySerialize(PBCollectionTemp.GetFromProgressBlockCollection(blocks), true);
this.fileStream.Position = this.urlFileInfo.FileLength;
this.fileStream.WriteAsync(dataBuffer, 0, dataBuffer.Length);
this.fileStream.Flush();
}
}
}

View File

@@ -9,71 +9,86 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.IO;
using System.Collections.Concurrent;
using System.IO;
namespace RRQMSocket.FileTransfer
{
/*
若汝棋茗
*/
/// <summary>
/// 传输文件Hash暂存字典
/// </summary>
public static class TransferFileHashDictionary
{
private static ConcurrentDictionary<string, FileInfo> filePathAndInfo = new ConcurrentDictionary<string, FileInfo>();
private static ConcurrentDictionary<string, UrlFileInfo> fileHashAndInfo = new ConcurrentDictionary<string, UrlFileInfo>();
private static ConcurrentDictionary<string, UrlFileInfo> filePathAndInfo = new ConcurrentDictionary<string, UrlFileInfo>();
/// <summary>
/// 字典存储文件Hash的最大数量默认为5000
/// 字典存储文件Hash的最大数量默认为10000
/// </summary>
public static int MaxCount { get; set; } = 5000;
public static int MaxCount { get; set; } = 10000;
/// <summary>
/// 添加文件信息
/// </summary>
/// <param name="filePath"></param>
public static void AddFile(string filePath)
/// <param name="breakpointResume"></param>
/// <returns></returns>
public static UrlFileInfo AddFile(string filePath, bool breakpointResume = true)
{
if (!File.Exists(filePath))
{
return;
}
FileInfo fileInfo = new FileInfo();
UrlFileInfo urlFileInfo = new UrlFileInfo();
using (FileStream stream = File.OpenRead(filePath))
{
fileInfo.FilePath = filePath;
fileInfo.FileLength = stream.Length;
fileInfo.FileName = Path.GetFileName(filePath);
fileInfo.FileHash = FileControler.GetStreamHash(stream);
urlFileInfo.FilePath = filePath;
urlFileInfo.FileLength = stream.Length;
urlFileInfo.FileName = Path.GetFileName(filePath);
if (breakpointResume)
{
urlFileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
}
}
AddFile(fileInfo);
AddFile(urlFileInfo);
return urlFileInfo;
}
/// <summary>
/// 添加文件信息
/// </summary>
/// <param name="fileInfo"></param>
public static void AddFile(FileInfo fileInfo)
/// <param name="urlFileInfo"></param>
public static void AddFile(UrlFileInfo urlFileInfo)
{
if (fileInfo == null)
if (urlFileInfo == null)
{
return;
}
filePathAndInfo.AddOrUpdate(fileInfo.FilePath, fileInfo, (key, oldValue) =>
filePathAndInfo.AddOrUpdate(urlFileInfo.FilePath, urlFileInfo, (key, oldValue) =>
{
return fileInfo;
return urlFileInfo;
});
if (!string.IsNullOrEmpty(urlFileInfo.FileHash))
{
fileHashAndInfo.AddOrUpdate(urlFileInfo.FileHash, urlFileInfo, (key, oldValue) =>
{
return urlFileInfo;
});
}
if (filePathAndInfo.Count > MaxCount)
{
foreach (var item in filePathAndInfo.Keys)
{
FileInfo info;
if (filePathAndInfo.TryRemove(item, out info))
if (filePathAndInfo.TryRemove(item, out _))
{
break;
}
}
}
if (fileHashAndInfo.Count > MaxCount)
{
foreach (var item in fileHashAndInfo.Keys)
{
if (fileHashAndInfo.TryRemove(item, out _))
{
break;
}
@@ -93,6 +108,84 @@ namespace RRQMSocket.FileTransfer
filePathAndInfo.Clear();
}
/// <summary>
/// 获取文件信息
/// </summary>
/// <param name="filePath"></param>
/// <param name="urlFileInfo"></param>
/// <param name="breakpointResume"></param>
/// <returns></returns>
public static bool GetFileInfo(string filePath, out UrlFileInfo urlFileInfo, bool breakpointResume)
{
if (filePathAndInfo == null)
{
urlFileInfo = null;
return false;
}
if (filePathAndInfo.ContainsKey(filePath))
{
urlFileInfo = filePathAndInfo[filePath];
if (File.Exists(filePath))
{
using (FileStream stream = File.OpenRead(filePath))
{
if (urlFileInfo.FileLength == stream.Length)
{
if (breakpointResume && urlFileInfo.FileHash == null)
{
urlFileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
AddFile(urlFileInfo);
}
return true;
}
}
}
}
urlFileInfo = null;
return false;
}
/// <summary>
/// 通过FileHash获取文件信息
/// </summary>
/// <param name="fileHash"></param>
/// <param name="urlFileInfo"></param>
/// <returns></returns>
public static bool GetFileInfoFromHash(string fileHash, out UrlFileInfo urlFileInfo)
{
if (fileHashAndInfo == null)
{
urlFileInfo = null;
return false;
}
if (string.IsNullOrEmpty(fileHash))
{
urlFileInfo = null;
return false;
}
if (fileHashAndInfo.TryGetValue(fileHash, out urlFileInfo))
{
if (urlFileInfo.FileHash == fileHash)
{
if (File.Exists(urlFileInfo.FilePath))
{
using (FileStream stream = File.OpenRead(urlFileInfo.FilePath))
{
if (urlFileInfo.FileLength == stream.Length)
{
return true;
}
}
}
}
}
urlFileInfo = null;
return false;
}
/// <summary>
/// 移除
/// </summary>
@@ -106,84 +199,5 @@ namespace RRQMSocket.FileTransfer
}
return filePathAndInfo.TryRemove(filePath, out _);
}
/// <summary>
/// 获取文件信息
/// </summary>
/// <param name="filePath"></param>
/// <param name="fileInfo"></param>
/// <param name="breakpointResume"></param>
/// <returns></returns>
public static bool GetFileInfo(string filePath, out FileInfo fileInfo, bool breakpointResume)
{
if (filePathAndInfo == null)
{
fileInfo = null;
return false;
}
if (filePathAndInfo.ContainsKey(filePath))
{
fileInfo = filePathAndInfo[filePath];
if (File.Exists(filePath))
{
using (FileStream stream = File.OpenRead(filePath))
{
if (fileInfo.FileLength == stream.Length)
{
if (breakpointResume && fileInfo.FileHash == null)
{
fileInfo.FileHash = FileControler.GetStreamHash(stream);
AddFile(fileInfo);
}
return true;
}
}
}
}
fileInfo = null;
return false;
}
/// <summary>
/// 通过FileHash获取文件信息
/// </summary>
/// <param name="fileHash"></param>
/// <param name="fileInfo"></param>
/// <returns></returns>
public static bool GetFileInfoFromHash(string fileHash, out FileInfo fileInfo)
{
if (filePathAndInfo == null)
{
fileInfo = null;
return false;
}
if (fileHash == null)
{
fileInfo = null;
return false;
}
foreach (var item in filePathAndInfo.Values)
{
if (item.FileHash == fileHash)
{
if (File.Exists(item.FilePath))
{
using (FileStream stream = File.OpenRead(item.FilePath))
{
if (item.FileLength == stream.Length)
{
fileInfo = item;
return true;
}
}
}
}
}
fileInfo = null;
return false;
}
}
}

View File

@@ -1,36 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在RRQMCore.XREF命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.ByteManager;
using System;
namespace RRQMSocket.FileTransfer
{
internal class TransferSetting
{
internal bool breakpointResume;
internal int bufferLength;
internal void Serialize(ByteBlock byteBlock)
{
byteBlock.Write(Convert.ToByte(breakpointResume));
byteBlock.Write(BitConverter.GetBytes(bufferLength));
}
internal static TransferSetting Deserialize(byte[] buffer, int offset)
{
TransferSetting transferSetting = new TransferSetting();
transferSetting.breakpointResume = BitConverter.ToBoolean(buffer, offset);
transferSetting.bufferLength = BitConverter.ToInt32(buffer, offset + 1);
return transferSetting;
}
}
}

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.IO;
using System.IO;
namespace RRQMSocket.FileTransfer
@@ -18,19 +17,83 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 文件信息类
/// </summary>
public class UrlFileInfo : FileInfo
public class UrlFileInfo
{
private string saveFullPath = string.Empty;
private int timeout = 30 * 1000;
/// <summary>
/// 文件哈希值
/// </summary>
public string FileHash { get; internal set; }
/// <summary>
/// 文件大小
/// </summary>
public long FileLength { get; internal set; }
/// <summary>
/// 文件名
/// </summary>
public string FileName { get; internal set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; internal set; }
/// <summary>
/// 传输标识
/// </summary>
public TransferFlags Flags { get; set; }
/// <summary>
/// 携带消息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 存放目录
/// </summary>
public string SaveFullPath
{
get { return saveFullPath; }
set
{
if (value == null)
{
value = string.Empty;
}
saveFullPath = value;
}
}
/// <summary>
/// 超时时间默认30*1000 ms
/// </summary>
public int Timeout
{
get { return timeout; }
set { timeout = value; }
}
/// <summary>
/// 请求传输类型
/// </summary>
public TransferType TransferType { get; internal set; }
/// <summary>
/// 生成下载请求必要信息
/// </summary>
/// <param name="path"></param>
/// <param name="restart"></param>
/// <param name="flags"></param>
/// <returns></returns>
public static UrlFileInfo CreatDownload(string path, bool restart = false)
public static UrlFileInfo CreateDownload(string path, TransferFlags flags)
{
UrlFileInfo fileInfo = new UrlFileInfo();
fileInfo.FilePath = path;
fileInfo.Restart = restart;
fileInfo.Flags = flags;
fileInfo.FileName = Path.GetFileName(path);
fileInfo.TransferType = TransferType.Download;
return fileInfo;
@@ -40,20 +103,19 @@ namespace RRQMSocket.FileTransfer
/// 生成上传请求必要信息
/// </summary>
/// <param name="path"></param>
/// <param name="breakpointResume"></param>
/// <param name="restart"></param>
/// <param name="flags"></param>
/// <returns></returns>
public static UrlFileInfo CreatUpload(string path, bool breakpointResume, bool restart = false)
public static UrlFileInfo CreateUpload(string path, TransferFlags flags)
{
UrlFileInfo fileInfo = new UrlFileInfo();
fileInfo.TransferType = TransferType.Upload;
using (FileStream stream = File.OpenRead(path))
{
fileInfo.Restart = restart;
fileInfo.Flags = flags;
fileInfo.FilePath = path;
if (breakpointResume)
if (flags.HasFlag(TransferFlags.BreakpointResume) || flags.HasFlag(TransferFlags.QuickTransfer))
{
fileInfo.FileHash = FileControler.GetStreamHash(stream);
fileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
}
fileInfo.FileLength = stream.Length;
fileInfo.FileName = Path.GetFileName(path);
@@ -63,57 +125,42 @@ namespace RRQMSocket.FileTransfer
}
/// <summary>
/// 重新开始
/// 复制
/// </summary>
public bool Restart { get; set; }
/// <summary>
/// 超时时间默认30秒
/// </summary>
public int Timeout { get; set; } = 30;
/// <summary>
/// 请求传输类型
/// </summary>
public TransferType TransferType { get; set; }
private string saveFolder = string.Empty;
/// <summary>
/// 存放目录
/// </summary>
public string SaveFolder
/// <param name="urlFileInfo"></param>
public void CopyFrom(UrlFileInfo urlFileInfo)
{
get { return saveFolder; }
set
{
if (value == null)
{
value = string.Empty;
}
saveFolder = value;
}
this.FileHash = urlFileInfo.FileHash;
this.FileLength = urlFileInfo.FileLength;
this.FileName = urlFileInfo.FileName;
this.FilePath = urlFileInfo.FilePath;
}
/// <summary>
/// 比较
/// 判断参数是否相同
/// </summary>
/// <param name="fileInfo"></param>
/// <param name="urlFileInfo"></param>
/// <returns></returns>
public bool Equals(UrlFileInfo fileInfo)
public bool Equals(UrlFileInfo urlFileInfo)
{
if (this.FileHash == fileInfo.FileHash)
{
return true;
}
else if (this.FilePath == fileInfo.FilePath)
{
return true;
}
else
if (urlFileInfo.FileHash != this.FileHash)
{
return false;
}
if (urlFileInfo.FileLength != this.FileLength)
{
return false;
}
if (urlFileInfo.FileName != this.FileName)
{
return false;
}
if (urlFileInfo.FilePath != this.FilePath)
{
return false;
}
return true;
}
}
}

View File

@@ -18,6 +18,14 @@ namespace RRQMSocket.FileTransfer
/// </summary>
public class FileClientConfig : TokenClientConfig
{
/// <summary>
/// 构造函数
/// </summary>
public FileClientConfig()
{
this.BufferLength = 64 * 1024;
}
/// <summary>
/// 默认接收文件的存放目录
/// </summary>
@@ -41,22 +49,37 @@ namespace RRQMSocket.FileTransfer
DependencyProperty.Register("ReceiveDirectory", typeof(string), typeof(FileClientConfig), string.Empty);
/// <summary>
/// 单次请求超时时间 min=5,max=60 单位:秒
/// 单次请求超时时间 min=5000,max=60*1000 ms
/// </summary>
public int Timeout
{
get { return (int)GetValue(TimeoutProperty); }
set
{
value = value < 5 ? 5 : (value > 60 ? 60 : value);
SetValue(TimeoutProperty, value);
}
}
/// <summary>
/// 单次请求超时时间 min=5,max=60 单位:秒, 所需类型<see cref="int"/>
/// 单次请求超时时间 min=5000,max=60*1000 ms, 所需类型<see cref="int"/>
/// </summary>
public static readonly DependencyProperty TimeoutProperty =
DependencyProperty.Register("Timeout", typeof(int), typeof(FileClientConfig), 5);
DependencyProperty.Register("Timeout", typeof(int), typeof(FileClientConfig), 10*1000);
/// <summary>
/// 数据包尺寸
/// </summary>
public int PacketSize
{
get { return (int)GetValue(PacketSizeProperty); }
set { SetValue(PacketSizeProperty, value); }
}
/// <summary>
/// 数据包尺寸, 所需类型<see cref="int"/>
/// </summary>
[RRQMCore.Range]
public static readonly DependencyProperty PacketSizeProperty =
DependencyProperty.Register("PacketSize", typeof(int), typeof(FileClientConfig), 1024 * 1024);
}
}

View File

@@ -19,20 +19,13 @@ namespace RRQMSocket.FileTransfer
public class FileServiceConfig : TokenServiceConfig
{
/// <summary>
/// 是否支持断点续传
/// 构造函数
/// </summary>
public bool BreakpointResume
public FileServiceConfig()
{
get { return (bool)GetValue(BreakpointResumeProperty); }
set { SetValue(BreakpointResumeProperty, value); }
this.BufferLength = 64 * 1024;
}
/// <summary>
/// 是否支持断点续传, 所需类型<see cref="bool"/>
/// </summary>
public static readonly DependencyProperty BreakpointResumeProperty =
DependencyProperty.Register("BreakpointResume", typeof(bool), typeof(FileServiceConfig), false);
/// <summary>
/// 最大下载速度
/// </summary>

View File

@@ -12,23 +12,28 @@
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 传输文件
/// 文件Hash检验类型
/// </summary>
public class TransferFileArgs
public enum FileHashType : byte
{
/// <summary>
/// 已接收的流位置
/// MD5
/// </summary>
public long StreamPosition { get; set; }
MD5,
/// <summary>
/// 接收的文件信息(不要手动更改里面任何内容)
/// SHA1
/// </summary>
public FileInfo FileInfo { get; set; }
SHA1,
/// <summary>
/// 传输文件进度
/// SHA256
/// </summary>
public float TransferProgressValue { get; set; }
SHA256,
/// <summary>
/// SHA512
/// </summary>
SHA512
}
}

View File

@@ -9,22 +9,26 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件进度块
/// 请求状态
/// </summary>
public class FileProgressBlock : FileBlock
public enum RequestStatus : byte
{
/// <summary>
/// 文件块长度
/// 未开始
/// </summary>
public long UnitLength { get; internal set; }
Hovering,
/// <summary>
/// 正在进行
/// </summary>
InProgress,
/// <summary>
/// 完成
/// </summary>
public bool Finished { get; internal set; }
Finished
}
}

View File

@@ -9,17 +9,21 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件路径事件类
/// 流操作类型
/// </summary>
public class FilePathEventArgs : TransferFileMessageArgs
public enum StreamOperationType : byte
{
/// <summary>
/// 获取或设置目标文件的最终路径,包含文件名及文件扩展名
///
/// </summary>
public string TargetPath { get; set; }
Read,
/// <summary>
/// 写
/// </summary>
Write
}
}

View File

@@ -9,30 +9,29 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System.Collections.Concurrent;
using System.IO;
using System;
namespace RRQMSocket.FileTransfer
{
internal static class TransferFileStreamDic
/// <summary>
/// 传输标识
/// </summary>
[Flags]
public enum TransferFlags
{
private static ConcurrentDictionary<string, FileStream> readOrWriteStreamDic = new ConcurrentDictionary<string, FileStream>();
/// <summary>
/// 无任何标识
/// </summary>
None = 0,
internal static FileStream GetFileStream(string path)
{
return readOrWriteStreamDic.GetOrAdd(path, (v) =>
{
return File.OpenRead(path);
});
}
/// <summary>
/// 断点续传
/// </summary>
BreakpointResume = 1,
internal static void DisposeFileStream(string path)
{
FileStream stream;
if (readOrWriteStreamDic.TryRemove(path, out stream))
{
stream.Dispose();
}
}
/// <summary>
/// 快速传输
/// </summary>
QuickTransfer = 2
}
}

View File

@@ -21,6 +21,6 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 文件信息
/// </summary>
public FileInfo FileInfo { get; internal set; }
public UrlFileInfo UrlFileInfo { get; internal set; }
}
}

View File

@@ -14,7 +14,7 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 操作文件事件类
/// </summary>
public class FileOperationEventArgs : FilePathEventArgs
public class FileOperationEventArgs : TransferFileMessageArgs
{
/// <summary>
/// 是否允许操作

View File

@@ -17,7 +17,7 @@ namespace RRQMSocket.FileTransfer
public class TransferFileMessageArgs : FileEventArgs
{
/// <summary>
/// 错误信息
/// 信息
/// </summary>
public string Message { get; internal set; }

View File

@@ -20,7 +20,7 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 获取当前传输文件信息
/// </summary>
FileInfo TransferFileInfo { get; }
UrlFileInfo TransferFileInfo { get; }
/// <summary>
/// 获取当前传输进度
@@ -36,10 +36,5 @@ namespace RRQMSocket.FileTransfer
/// 获取当前传输状态
/// </summary>
TransferStatus TransferStatus { get; }
/// <summary>
/// 获取当前传输文件包
/// </summary>
ProgressBlockCollection FileBlocks { get; }
}
}

View File

@@ -65,6 +65,10 @@ Demohttps://gitee.com/RRQM_OS/RRQMBox</Description>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RRQMSocket.RPC\RRQMSocket.RPC.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="RRQMCore">
<HintPath>..\..\RRQMCore\RRQMCore\bin\Debug\net45\RRQMCore.dll</HintPath>

File diff suppressed because it is too large Load Diff

View File

@@ -21,20 +21,10 @@ namespace RRQMSocket.FileTransfer
{
#region
private bool breakpointResume;
private long maxDownloadSpeed;
private long maxUploadSpeed;
/// <summary>
/// 是否支持断点续传
/// </summary>
public bool BreakpointResume
{
get { return breakpointResume; }
}
/// <summary>
/// 获取下载速度
/// </summary>
@@ -105,13 +95,12 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 载入配置
/// </summary>
/// <param name="serverConfig"></param>
protected override void LoadConfig(ServiceConfig serverConfig)
/// <param name="serviceConfig"></param>
protected override void LoadConfig(ServiceConfig serviceConfig)
{
base.LoadConfig(serverConfig);
this.breakpointResume = (bool)serverConfig.GetValue(FileServiceConfig.BreakpointResumeProperty);
this.maxDownloadSpeed = (long)serverConfig.GetValue(FileServiceConfig.MaxDownloadSpeedProperty);
this.maxUploadSpeed = (long)serverConfig.GetValue(FileServiceConfig.MaxUploadSpeedProperty);
base.LoadConfig(serviceConfig);
this.maxDownloadSpeed = (long)serviceConfig.GetValue(FileServiceConfig.MaxDownloadSpeedProperty);
this.maxUploadSpeed = (long)serviceConfig.GetValue(FileServiceConfig.MaxUploadSpeedProperty);
}
/// <summary>
@@ -122,8 +111,6 @@ namespace RRQMSocket.FileTransfer
protected override void OnCreateSocketCliect(FileSocketClient socketClient, CreateOption creatOption)
{
base.OnCreateSocketCliect(socketClient, creatOption);
socketClient.breakpointResume = this.BreakpointResume;
socketClient.MaxDownloadSpeed = this.MaxDownloadSpeed;
socketClient.MaxUploadSpeed = this.MaxUploadSpeed;
if (creatOption.NewCreate)

View File

@@ -10,7 +10,6 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.ByteManager;
using RRQMCore.IO;
using RRQMCore.Log;
using RRQMCore.Serialization;
using RRQMSocket.RPC.RRQMRPC;
@@ -18,6 +17,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
namespace RRQMSocket.FileTransfer
@@ -27,6 +27,40 @@ namespace RRQMSocket.FileTransfer
/// </summary>
public class FileSocketClient : RPCSocketClient, IFileService, IFileClient
{
/// <summary>
/// 传输文件之前
/// </summary>
internal RRQMFileOperationEventHandler BeforeFileTransfer;
/// <summary>
/// 当文件传输完成时
/// </summary>
internal RRQMTransferFileMessageEventHandler FinishedFileTransfer;
private long dataTransferLength;
private long maxDownloadSpeed = 1024 * 1024;
private long maxUploadSpeed = 1024 * 1024;
private long position;
private float progress;
private string rrqmPath;
private long speed;
private Stopwatch stopwatch = new Stopwatch();
private long tempLength;
private long timeTick;
private TransferStatus transferStatus;
private UrlFileInfo transferUrlFileInfo;
static FileSocketClient()
{
AddUsedProtocol(110, "同步设置");
@@ -39,19 +73,13 @@ namespace RRQMSocket.FileTransfer
AddUsedProtocol(117, "上传分块");
AddUsedProtocol(118, "停止上传");
AddUsedProtocol(119, "确认上传完成");
AddUsedProtocol(120, "智能包调节");
for (short i = 121; i < 200; i++)
{
AddUsedProtocol(i, "保留协议");
}
}
#region
private long maxDownloadSpeed = 1024 * 1024;
private long maxUploadSpeed = 1024 * 1024;
/// <summary>
/// 获取当前传输文件包
/// </summary>
public ProgressBlockCollection FileBlocks { get { return fileBlocks == null ? null : fileBlocks; } }
/// <summary>
/// 每秒最大下载速度Byte,不可小于1024
/// </summary>
@@ -64,8 +92,7 @@ namespace RRQMSocket.FileTransfer
{
value = 1024;
}
maxDownloadSpeed = value;
MaxSpeedChanged(maxDownloadSpeed);
this.maxDownloadSpeed = value;
}
}
@@ -81,15 +108,14 @@ namespace RRQMSocket.FileTransfer
{
value = 1024;
}
maxUploadSpeed = value;
MaxSpeedChanged(maxUploadSpeed);
this.maxUploadSpeed = value;
}
}
/// <summary>
/// 获取当前传输文件信息
/// </summary>
public FileInfo TransferFileInfo { get { return fileBlocks == null ? null : fileBlocks.UrlFileInfo; } }
public UrlFileInfo TransferFileInfo { get => this.transferUrlFileInfo; }
/// <summary>
/// 获取当前传输进度
@@ -98,18 +124,11 @@ namespace RRQMSocket.FileTransfer
{
get
{
if (fileBlocks == null)
if (transferUrlFileInfo == null)
{
return 0;
}
if (fileBlocks.UrlFileInfo != null)
{
this.progress = fileBlocks.UrlFileInfo.FileLength > 0 ? (float)position / fileBlocks.UrlFileInfo.FileLength : 0;//计算下载完成进度
}
else
{
this.progress = 0;
}
this.progress = transferUrlFileInfo.FileLength > 0 ? (float)position / transferUrlFileInfo.FileLength : 0;//计算下载完成进度
return progress <= 1 ? progress : 1;
}
}
@@ -130,39 +149,10 @@ namespace RRQMSocket.FileTransfer
/// <summary>
/// 获取当前传输状态
/// </summary>
public TransferStatus TransferStatus { get; private set; }
#endregion
#region
internal bool breakpointResume;
private bool bufferLengthChanged;
private long dataTransferLength;
private ProgressBlockCollection fileBlocks;
private long position;
private float progress;
private long speed;
private Stopwatch stopwatch = new Stopwatch();
private long tempLength;
private long timeTick;
private RRQMStream uploadFileStream;
#endregion
#region
/// <summary>
/// 传输文件之前
/// </summary>
internal RRQMFileOperationEventHandler BeforeFileTransfer;
/// <summary>
/// 当文件传输完成时
/// </summary>
internal RRQMTransferFileMessageEventHandler FinishedFileTransfer;
#endregion
public TransferStatus TransferStatus
{
get { return transferStatus; }
}
/// <summary>
/// 释放资源
@@ -170,6 +160,7 @@ namespace RRQMSocket.FileTransfer
public override void Dispose()
{
base.Dispose();
this.ResetVariable();
}
/// <summary>
@@ -178,8 +169,16 @@ namespace RRQMSocket.FileTransfer
public override void Recreate()
{
base.Recreate();
this.maxDownloadSpeed = 1024 * 1024;
this.maxUploadSpeed = 1024 * 1024;
}
/// <summary>
/// 文件辅助类处理其他协议
/// </summary>
/// <param name="procotol"></param>
/// <param name="byteBlock"></param>
protected virtual void FileSocketClientHandleDefaultData(short? procotol, ByteBlock byteBlock)
{
this.OnHandleDefaultData(procotol, byteBlock);
}
/// <summary>
@@ -195,181 +194,113 @@ namespace RRQMSocket.FileTransfer
{
case 110:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
if (this.TransferStatus == TransferStatus.Download)
{
this.MaxSpeedChanged(this.maxDownloadSpeed);
}
else
{
this.MaxSpeedChanged(this.maxUploadSpeed);
}
TransferSetting transferSetting = new TransferSetting();
transferSetting.breakpointResume = this.breakpointResume;
transferSetting.bufferLength = this.BufferLength;
transferSetting.Serialize(returnByteBlock);
this.bufferLengthChanged = false;
this.InternalSend(111, returnByteBlock);
//this.P110_SynchronizeTransferSetting();
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 112:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
UrlFileInfo fileInfo = SerializeConvert.RRQMBinaryDeserialize<UrlFileInfo>(buffer, 2);
RequestDownload(returnByteBlock, fileInfo);
this.InternalSend(111, returnByteBlock);
P112_RequestDownload(fileInfo);
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 113:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
DownloadBlockData(returnByteBlock, buffer);
this.InternalSend(111, returnByteBlock.Buffer, 0, (int)returnByteBlock.Length, true);
P113_DownloadBlockData(byteBlock);
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 114:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
this.fileBlocks = null;
this.TransferStatus = TransferStatus.None;
returnByteBlock.Write(1);
this.InternalSend(111, returnByteBlock);
P114_StopDownload();
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 115:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
DownloadFinished(returnByteBlock);
this.InternalSend(111, returnByteBlock);
P115_DownloadFinished();
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 116:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
bool restart = BitConverter.ToBoolean(byteBlock.Buffer, 2);
PBCollectionTemp blocks = SerializeConvert.RRQMBinaryDeserialize<PBCollectionTemp>(byteBlock.Buffer, 3);
RequestUpload(returnByteBlock, blocks, restart);
this.InternalSend(111, returnByteBlock);
UrlFileInfo urlFileInfo = SerializeConvert.RRQMBinaryDeserialize<UrlFileInfo>(buffer, 2);
P116_RequestUpload(urlFileInfo);
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 117:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
UploadBlockData(returnByteBlock, byteBlock);
this.InternalSend(111, returnByteBlock);
P117_UploadBlockData(buffer);
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 118:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
StopUpload(returnByteBlock);
this.InternalSend(111, returnByteBlock);
P118_StopUpload();
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
case 119:
{
ByteBlock returnByteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
UploadFinished(returnByteBlock);
this.InternalSend(111, returnByteBlock);
P119_UploadFinished();
}
catch (Exception ex)
{
Logger.Debug(LogType.Error, this, ex.Message, ex);
}
finally
{
returnByteBlock.Dispose();
}
break;
}
default:
@@ -380,24 +311,6 @@ namespace RRQMSocket.FileTransfer
}
}
/// <summary>
/// 文件辅助类处理其他协议
/// </summary>
/// <param name="procotol"></param>
/// <param name="byteBlock"></param>
protected virtual void FileSocketClientHandleDefaultData(short? procotol, ByteBlock byteBlock)
{
this.OnHandleDefaultData(procotol, byteBlock);
}
/// <summary>
/// 当BufferLength改变值的时候
/// </summary>
protected override void OnBufferLengthChanged()
{
bufferLengthChanged = true;
}
/// <summary>
/// 继承
/// </summary>
@@ -414,7 +327,7 @@ namespace RRQMSocket.FileTransfer
else
{
//在这一秒中
switch (this.TransferStatus)
switch (this.transferStatus)
{
case TransferStatus.Upload:
if (this.dataTransferLength > this.maxUploadSpeed)
@@ -448,188 +361,222 @@ namespace RRQMSocket.FileTransfer
return DateTime.Now.Ticks / 10000000;
}
private void MaxSpeedChanged(long speed)
private FileOperationEventArgs OnBeforeFileTransfer(UrlFileInfo urlFileInfo)
{
if (speed < 1024 * 1024 * 50)
FileOperationEventArgs args = new FileOperationEventArgs();
args.UrlFileInfo = urlFileInfo;
args.TransferType = urlFileInfo.TransferType;
args.IsPermitOperation = true;
if (urlFileInfo.TransferType == TransferType.Download)
{
this.SetBufferLength(1024 * 10);
//下载
urlFileInfo.FilePath = Path.GetFullPath(urlFileInfo.FilePath);
}
else if (speed < 1024 * 1024 * 100)
try
{
this.SetBufferLength(1024 * 64);
this.BeforeFileTransfer?.Invoke(this, args);//触发 接收文件事件
}
catch (Exception ex)
{
this.Logger.Debug(LogType.Error, this, $"在事件{nameof(BeforeFileTransfer)}中发生异常", ex);
}
if (urlFileInfo.TransferType == TransferType.Upload)
{
urlFileInfo.SaveFullPath = Path.GetFullPath(string.IsNullOrEmpty(urlFileInfo.SaveFullPath) ? urlFileInfo.FileName : urlFileInfo.SaveFullPath);
this.rrqmPath = urlFileInfo.SaveFullPath + ".rrqm";
}
this.transferUrlFileInfo = urlFileInfo;
return args;
}
private void OnFinishedFileTransfer(TransferType transferType)
{
if (!string.IsNullOrEmpty(this.transferUrlFileInfo.FileHash))
{
TransferFileHashDictionary.AddFile(this.transferUrlFileInfo);
}
TransferFileMessageArgs args = new TransferFileMessageArgs();
args.UrlFileInfo = this.transferUrlFileInfo;
args.TransferType = transferType;
if (transferType == TransferType.Download)
{
FileStreamPool.DisposeReadStream(this.transferUrlFileInfo.FilePath);
}
else
{
this.SetBufferLength(1024 * 512);
}
}
#region
private void DownloadBlockData(ByteBlock byteBlock, byte[] buffer)
{
if (this.TransferStatus != TransferStatus.Download)
{
byteBlock.Buffer[6] = 0;
return;
FileStreamPool.DisposeWriteStream(this.rrqmPath, true);
this.rrqmPath = null;
}
this.transferStatus = TransferStatus.None;
this.transferUrlFileInfo = null;
try
{
long position = BitConverter.ToInt64(buffer, 2);
long requestLength = BitConverter.ToInt64(buffer, 10);
if (FileBaseTool.ReadFileBytes(fileBlocks.UrlFileInfo.FilePath, position, byteBlock, 7, (int)requestLength))
{
Speed.downloadSpeed += requestLength;
this.position = position + requestLength;
this.tempLength += requestLength;
this.dataTransferLength += requestLength;
if (this.bufferLengthChanged)
{
byteBlock.Buffer[6] = 3;
}
else
{
byteBlock.Buffer[6] = 1;
}
}
else
{
byteBlock.Buffer[6] = 2;
}
this.FinishedFileTransfer?.Invoke(this, args);
}
catch
catch (Exception ex)
{
byteBlock.Buffer[6] = 2;
this.Logger.Debug(LogType.Error, this, $"在事件{nameof(FinishedFileTransfer)}中发生异常", ex);
}
this.ResetVariable();
}
private void DownloadFinished(ByteBlock byteBlock)
private void P112_RequestDownload(UrlFileInfo urlFileInfo)
{
TransferFileStreamDic.DisposeFileStream(this.fileBlocks.UrlFileInfo.FilePath);
byteBlock.Write(1);
FilePathEventArgs args = new FilePathEventArgs();
args.FileInfo = this.fileBlocks.UrlFileInfo;
this.TransferStatus = TransferStatus.None;
args.TransferType = TransferType.Download;
args.TargetPath = args.FileInfo.FilePath;
this.FinishedFileTransfer?.Invoke(this, args);
this.fileBlocks = null;
}
private void RequestDownload(ByteBlock byteBlock, UrlFileInfo urlFileInfo)
{
FileOperationEventArgs args = new FileOperationEventArgs();
args.FileInfo = urlFileInfo;
args.IsPermitOperation = true;
args.TargetPath = args.FileInfo.FilePath;
args.TransferType = TransferType.Download;
this.BeforeFileTransfer?.Invoke(this, args);
string filePath = args.TargetPath;
FileOperationEventArgs args = OnBeforeFileTransfer(urlFileInfo);
FileWaitResult waitResult = new FileWaitResult();
if (!args.IsPermitOperation)
{
waitResult.Message = string.IsNullOrEmpty(args.Message) ? "服务器拒绝下载" : args.Message;
waitResult.Status = 2;
this.TransferStatus = TransferStatus.None;
this.transferStatus = TransferStatus.None;
}
else if (!File.Exists(urlFileInfo.FilePath))
{
waitResult.Message = string.Format("文件不存在", filePath);
waitResult.Message = $"路径{urlFileInfo.FilePath}文件不存在";
waitResult.Status = 2;
this.TransferStatus = TransferStatus.None;
this.transferStatus = TransferStatus.None;
}
else
{
this.TransferStatus = TransferStatus.Download;
waitResult.Message = null;
waitResult.Status = 1;
FileInfo fileInfo;
UrlFileInfo fileInfo;
if (!TransferFileHashDictionary.GetFileInfo(filePath, out fileInfo, breakpointResume))
if (!TransferFileHashDictionary.GetFileInfo(urlFileInfo.FilePath, out fileInfo, urlFileInfo.Flags.HasFlag(TransferFlags.BreakpointResume)))
{
fileInfo = new FileInfo();
using (FileStream stream = File.OpenRead(filePath))
{
fileInfo.FilePath = filePath;
fileInfo.FileLength = stream.Length;
fileInfo.FileName = Path.GetFileName(filePath);
if (this.breakpointResume)
{
fileInfo.FileHash = FileControler.GetStreamHash(stream);
}
TransferFileHashDictionary.AddFile(fileInfo);
}
fileInfo = TransferFileHashDictionary.AddFile(urlFileInfo.FilePath, urlFileInfo.Flags.HasFlag(TransferFlags.BreakpointResume));
}
urlFileInfo.CopyFrom(fileInfo);
if (FileStreamPool.LoadReadStream(ref urlFileInfo, out string mes))
{
this.transferStatus = TransferStatus.Download;
waitResult.Message = null;
waitResult.Status = 1;
this.transferUrlFileInfo = urlFileInfo;
waitResult.PBCollectionTemp = new PBCollectionTemp();
waitResult.PBCollectionTemp.UrlFileInfo = urlFileInfo;
}
else
{
waitResult.Message = mes;
waitResult.Status = 2;
}
urlFileInfo.Copy(fileInfo);
fileBlocks = FileBaseTool.GetProgressBlockCollection(urlFileInfo, this.breakpointResume);
waitResult.PBCollectionTemp = PBCollectionTemp.GetFromProgressBlockCollection(fileBlocks);
}
byteBlock.Write(SerializeConvert.RRQMBinarySerialize(waitResult, true));
this.SendDefaultObject(waitResult);
}
private void RequestUpload(ByteBlock byteBlock, PBCollectionTemp requestBlocks, bool restart)
private void P113_DownloadBlockData(ByteBlock receivedByteBlock)
{
FileWaitResult waitResult = new FileWaitResult();
FileOperationEventArgs args = new FileOperationEventArgs();
args.FileInfo = requestBlocks.UrlFileInfo;
args.TargetPath = Path.Combine(requestBlocks.UrlFileInfo.SaveFolder, requestBlocks.UrlFileInfo.FileName);
args.IsPermitOperation = true;
this.BeforeFileTransfer?.Invoke(this, args);//触发 接收文件事件
requestBlocks.UrlFileInfo.FilePath = args.TargetPath;
receivedByteBlock.Pos = 2;
long position = receivedByteBlock.ReadInt64();
int requestLength = receivedByteBlock.ReadInt32();
ByteBlock byteBlock = this.BytePool.GetByteBlock(requestLength + 7);
if (this.transferStatus != TransferStatus.Download)
{
byteBlock.Buffer[6] = 0;
}
string mes;
if (FileStreamPool.ReadFile(transferUrlFileInfo.FilePath, out mes, position, byteBlock, 7, requestLength))
{
Speed.downloadSpeed += requestLength;
this.position = position + requestLength;
this.tempLength += requestLength;
this.dataTransferLength += requestLength;
byteBlock.Buffer[6] = 1;
}
else
{
byteBlock.Position = 6;
byteBlock.Write((byte)2);
byteBlock.Write(Encoding.UTF8.GetBytes(string.IsNullOrEmpty(mes) ? "未知错误" : mes));
}
try
{
if (this.Online)
{
this.InternalSend(111, byteBlock.Buffer, 0, byteBlock.Len, true);
}
}
finally
{
byteBlock.Dispose();
}
}
private void P114_StopDownload()
{
this.transferUrlFileInfo = null;
this.transferStatus = TransferStatus.None;
this.InternalSend(111, new byte[] { 1 }, 0, 1);
}
private void P115_DownloadFinished()
{
if (this.transferStatus == TransferStatus.None)
{
this.InternalSend(111, new byte[] { 1 }, 0, 1);
return;
}
this.InternalSend(111, new byte[] { 1 }, 0, 1);
OnFinishedFileTransfer(TransferType.Download);
}
private void P116_RequestUpload(UrlFileInfo urlFileInfo)
{
FileOperationEventArgs args = OnBeforeFileTransfer(urlFileInfo);
FileWaitResult waitResult = new FileWaitResult();
if (!args.IsPermitOperation)
{
waitResult.Status = 2;
waitResult.Message = string.IsNullOrEmpty(args.Message) ? "服务器拒绝上传" : args.Message;
}
else if (FileControler.FileIsOpen(requestBlocks.UrlFileInfo.FilePath))
{
waitResult.Status = 2;
waitResult.Message = "该文件已被打开,或许正在由其他客户端上传";
}
else
{
this.TransferStatus = TransferStatus.Upload;
restart = this.breakpointResume ? restart : true;
if (!restart)
this.transferStatus = TransferStatus.Upload;
this.transferUrlFileInfo = urlFileInfo;
if (urlFileInfo.Flags.HasFlag(TransferFlags.QuickTransfer) && TransferFileHashDictionary.GetFileInfoFromHash(urlFileInfo.FileHash, out UrlFileInfo oldUrlFileInfo))
{
FileInfo fileInfo;
if (TransferFileHashDictionary.GetFileInfoFromHash(requestBlocks.UrlFileInfo.FileHash, out fileInfo))
try
{
try
if (urlFileInfo.FilePath != oldUrlFileInfo.FilePath)
{
if (fileInfo.FilePath != requestBlocks.UrlFileInfo.FilePath)
{
File.Copy(fileInfo.FilePath, requestBlocks.UrlFileInfo.FilePath);
}
this.fileBlocks = FileBaseTool.GetProgressBlockCollection(requestBlocks.UrlFileInfo, this.breakpointResume);
foreach (var item in this.fileBlocks)
{
item.Finished = true;
}
waitResult.Status = 3;
waitResult.Message = null;
File.Copy(oldUrlFileInfo.FilePath, urlFileInfo.FilePath, true);
}
byteBlock.Write(SerializeConvert.RRQMBinarySerialize(waitResult, true));
return;
}
catch
{
}
waitResult.Status = 3;
waitResult.Message = null;
this.SendDefaultObject(waitResult);
return;
}
catch (Exception ex)
{
waitResult.Status = 2;
waitResult.Message = ex.Message;
this.Logger.Debug(LogType.Error, this, "在处理快速上传时发生异常。", ex);
}
}
try
{
ProgressBlockCollection blocks = requestBlocks.ToPBCollection();
uploadFileStream = RRQMStream.GetRRQMStream(ref blocks, restart, this.breakpointResume);
blocks.UrlFileInfo.FilePath = requestBlocks.UrlFileInfo.FilePath;
this.fileBlocks = blocks;
waitResult.Status = 1;
waitResult.Message = null;
waitResult.PBCollectionTemp = PBCollectionTemp.GetFromProgressBlockCollection(blocks);
ProgressBlockCollection blocks = ProgressBlockCollection.CreateProgressBlockCollection(urlFileInfo);
if (FileStreamPool.LoadWriteStream(ref blocks, false, out string mes))
{
waitResult.Status = 1;
waitResult.Message = null;
waitResult.PBCollectionTemp = PBCollectionTemp.GetFromProgressBlockCollection(blocks);
}
else
{
waitResult.Status = 2;
waitResult.Message = mes;
}
}
catch (Exception ex)
{
@@ -639,83 +586,107 @@ namespace RRQMSocket.FileTransfer
}
}
byteBlock.Write(SerializeConvert.RRQMBinarySerialize(waitResult, true));
this.SendDefaultObject(waitResult);
}
private void StopUpload(ByteBlock byteBlock)
private void P117_UploadBlockData(byte[] buffer)
{
FileBaseTool.SaveProgressBlockCollection(this.uploadFileStream, this.fileBlocks);
this.uploadFileStream.Dispose();
this.uploadFileStream = null;
byteBlock.Write(1);
}
private void UploadBlockData(ByteBlock byteBlock, ByteBlock receivedbyteBlock)
{
if (this.TransferStatus != TransferStatus.Upload)
ByteBlock byteBlock = this.BytePool.GetByteBlock(this.BufferLength);
try
{
byteBlock.Write(4);
return;
}
byte status = receivedbyteBlock.Buffer[2];
int index = BitConverter.ToInt32(receivedbyteBlock.Buffer, 3);
long position = BitConverter.ToInt64(receivedbyteBlock.Buffer, 7);
long submitLength = BitConverter.ToInt64(receivedbyteBlock.Buffer, 15);
string mes;
if (FileBaseTool.WriteFile(this.uploadFileStream, out mes, position, receivedbyteBlock.Buffer, 23, (int)submitLength))
{
this.position = position + submitLength;
this.tempLength += submitLength;
this.dataTransferLength += submitLength;
Speed.uploadSpeed += submitLength;
if (this.bufferLengthChanged)
if (this.transferStatus != TransferStatus.Upload)
{
byteBlock.Write(3);
byteBlock.Write((byte)4);
}
byte status = buffer[2];
int index = BitConverter.ToInt32(buffer, 3);
long position = BitConverter.ToInt64(buffer, 7);
int submitLength = BitConverter.ToInt32(buffer, 15);
string mes;
if (FileStreamPool.WriteFile(this.rrqmPath, out mes, out RRQMStream stream, position, buffer, 19, submitLength))
{
this.position = position + submitLength;
this.tempLength += submitLength;
this.dataTransferLength += submitLength;
Speed.uploadSpeed += submitLength;
byteBlock.Write((byte)1);
if (status == 1)
{
FileBlock fileProgress = stream.Blocks.FirstOrDefault(a => a.Index == index);
fileProgress.RequestStatus = RequestStatus.Finished;
stream.SaveProgressBlockCollection();
}
}
else
{
byteBlock.Write(1);
}
if (status == 1)
{
FileProgressBlock fileProgress = this.fileBlocks.FirstOrDefault(a => a.Index == index);
fileProgress.Finished = true;
FileBaseTool.SaveProgressBlockCollection(this.uploadFileStream, this.fileBlocks);
byteBlock.Write((byte)2);
byteBlock.Write(Encoding.UTF8.GetBytes(mes));
Logger.Debug(LogType.Error, this, $"上传文件写入错误,信息:{mes}");
}
this.InternalSend(111, byteBlock);
}
else
catch (Exception ex)
{
byteBlock.Write(2);
Logger.Debug(LogType.Error, this, "上传文件写入错误:" + mes);
Logger.Debug(LogType.Error, this, "上传文件错误", ex);
}
finally
{
byteBlock.Dispose();
}
}
private void UploadFinished(ByteBlock byteBlock)
private void P118_StopUpload()
{
TransferFileHashDictionary.AddFile(this.TransferFileInfo);
if (this.uploadFileStream != null)
try
{
RRQMStream.FileFinished(this.uploadFileStream);
this.uploadFileStream = null;
FileStreamPool.SaveProgressBlockCollection(this.rrqmPath);
FileStreamPool.DisposeWriteStream(this.rrqmPath, false);
this.ResetVariable();
this.InternalSend(111, new byte[] { 1 }, 0, 1);
}
if (this.fileBlocks != null)
catch (Exception ex)
{
TransferFileHashDictionary.AddFile(this.fileBlocks.UrlFileInfo);
FilePathEventArgs args = new FilePathEventArgs();
args.FileInfo = this.fileBlocks.UrlFileInfo;
args.TargetPath = args.FileInfo.FilePath;
args.TransferType = TransferType.Upload;
this.FinishedFileTransfer?.Invoke(this, args);
this.fileBlocks = null;
this.Logger.Debug(LogType.Error, this, "客户端请求停止上传时发生异常", ex);
}
byteBlock.Write(1);
}
#endregion
private void P119_UploadFinished()
{
if (this.transferStatus == TransferStatus.None)
{
this.InternalSend(111, new byte[] { 1 }, 0, 1);
return;
}
this.InternalSend(111, new byte[] { 1 }, 0, 1);
OnFinishedFileTransfer(TransferType.Upload);
}
private void ResetVariable()
{
this.transferStatus = TransferStatus.None;
this.transferUrlFileInfo = null;
this.progress = 0;
this.speed = 0;
if (!string.IsNullOrEmpty(this.rrqmPath))
{
FileStreamPool.DisposeWriteStream(this.rrqmPath, false);
this.rrqmPath = null;
}
}
private void SendDefaultObject(object obj)
{
ByteBlock byteBlock = this.BytePool.GetByteBlock(this.BufferLength);
byteBlock.Write(SerializeConvert.RRQMBinarySerialize(obj, true));
try
{
this.InternalSend(111, byteBlock);
}
finally
{
byteBlock.Dispose();
}
}
}
}