修复文件

This commit is contained in:
若汝棋茗
2021-08-13 21:05:54 +08:00
parent 1bc8e48431
commit 985ab8ab36
228 changed files with 0 additions and 26391 deletions

View File

@@ -1,40 +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 FileBlock
{
/// <summary>
/// 文件快索引
/// </summary>
public int Index { get; internal set; }
/// <summary>
/// 文件流位置
/// </summary>
public long Position { get; internal set; }
/// <summary>
/// 文件块长度
/// </summary>
public long UnitLength { get; internal set; }
/// <summary>
/// 请求状态
/// </summary>
public RequestStatus RequestStatus { get; internal set; }
}
}

View File

@@ -1,80 +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.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,250 +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.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

@@ -1,28 +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.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

@@ -1,20 +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.Run;
namespace RRQMSocket.FileTransfer
{
internal class FileWaitResult : WaitResult
{
public PBCollectionTemp PBCollectionTemp { get; set; }
}
}

View File

@@ -1,64 +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 System.Collections.Generic;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 临时序列化
/// </summary>
public class PBCollectionTemp
{
/// <summary>
/// 文件信息
/// </summary>
public UrlFileInfo UrlFileInfo { get; internal set; }
/// <summary>
/// 块集合
/// </summary>
public List<FileBlock> Blocks { get; internal set; }
/// <summary>
/// 从文件块转换
/// </summary>
/// <param name="progressBlocks"></param>
/// <returns></returns>
public static PBCollectionTemp GetFromProgressBlockCollection(ProgressBlockCollection progressBlocks)
{
if (progressBlocks == null)
{
return null;
}
PBCollectionTemp collectionTemp = new PBCollectionTemp();
collectionTemp.UrlFileInfo = progressBlocks.UrlFileInfo;
collectionTemp.Blocks = new List<FileBlock>();
collectionTemp.Blocks.AddRange(progressBlocks);
return collectionTemp;
}
/// <summary>
/// 转换为ProgressBlockCollection
/// </summary>
/// <returns></returns>
public ProgressBlockCollection ToPBCollection()
{
ProgressBlockCollection progressBlocks = new ProgressBlockCollection();
progressBlocks.UrlFileInfo = this.UrlFileInfo;
if (this.Blocks != null)
{
progressBlocks.AddRange(this.Blocks);
}
return progressBlocks;
}
}
}

View File

@@ -1,106 +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.Serialization;
using System;
using System.IO;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件进度块集合
/// </summary>
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>
/// <param name="path"></param>
internal void Save(string path)
{
if (File.Exists(path))
{
File.Delete(path);
}
byte[] buffer = SerializeConvert.RRQMBinarySerialize(this, true);
using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
fileStream.Write(buffer, 0, buffer.Length);
}
}
/// <summary>
/// 读取
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
internal static ProgressBlockCollection Read(string path)
{
try
{
using (FileStream stream = File.OpenRead(path))
{
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
return SerializeConvert.RRQMBinaryDeserialize<ProgressBlockCollection>(buffer, 0);
}
}
catch (Exception)
{
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

@@ -1,157 +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.Serialization;
using System;
using System.IO;
namespace RRQMSocket.FileTransfer
{
internal class RRQMStream
{
internal int reference;
private ProgressBlockCollection blocks;
private FileStream fileStream;
private string rrqmPath;
private StreamOperationType streamType;
private UrlFileInfo urlFileInfo;
private RRQMStream()
{
}
public ProgressBlockCollection Blocks { get { return blocks; } }
public FileStream FileStream
{
get { return fileStream; }
}
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()
{
this.blocks = null;
this.urlFileInfo = null;
if (this.fileStream != 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

@@ -1,93 +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 System;
using System.Collections;
using System.Collections.Generic;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 只读
/// </summary>
/// <typeparam name="T"></typeparam>
public class ReadOnlyList<T> : IEnumerable<T>
{
private List<T> list = new List<T>();
internal void Add(T block)
{
list.Add(block);
}
internal void AddRange(IEnumerable<T> collection)
{
list.AddRange(collection);
}
internal void Remove(T block)
{
list.Remove(block);
}
internal void RemoveAt(int index)
{
list.RemoveAt(index);
}
internal void RemoveAll(Predicate<T> match)
{
list.RemoveAll(match);
}
internal void RemoveRange(int index, int range)
{
list.RemoveRange(index, range);
}
internal void Clear()
{
list.Clear();
}
internal void Insert(int index, T item)
{
list.Insert(index, item);
}
internal void InsertRange(int index, IEnumerable<T> collection)
{
list.InsertRange(index, collection);
}
/// <summary>
/// 返回迭代器
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
return this.list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.list.GetEnumerator();
}
/// <summary>
/// 获取对象
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public T this[int index] { get { return list[index]; } }
}
}

View File

@@ -1,22 +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>
internal class Speed
{
internal static long downloadSpeed;
internal static long uploadSpeed;
}
}

View File

@@ -1,92 +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 System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 传输集合
/// </summary>
public class TransferCollection : IEnumerable<UrlFileInfo>
{
internal TransferCollection()
{
list = new List<UrlFileInfo>();
}
internal event RRQMMessageEventHandler OnCollectionChanged;
private List<UrlFileInfo> list;
/// <summary>
/// 返回一个循环访问集合的枚举器
/// </summary>
/// <returns></returns>
public IEnumerator<UrlFileInfo> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}
internal void Add(UrlFileInfo fileInfo)
{
this.list.Add(fileInfo);
Task.Run(() =>
{
OnCollectionChanged?.Invoke(null, new MesEventArgs("添加"));
});
}
internal void Clear()
{
this.list.Clear();
Task.Run(() =>
{
OnCollectionChanged?.Invoke(null, new MesEventArgs("清空"));
});
}
internal bool Remove(UrlFileInfo fileInfo)
{
Task.Run(() =>
{
OnCollectionChanged?.Invoke(null, new MesEventArgs("移除"));
});
return this.list.Remove(fileInfo);
}
internal bool GetFirst(out UrlFileInfo fileInfo)
{
lock (this)
{
if (this.list.Count > 0)
{
fileInfo = this.list[0];
this.list.RemoveAt(0);
Task.Run(() =>
{
OnCollectionChanged?.Invoke(null, new MesEventArgs("进入传输"));
});
return true;
}
fileInfo = null;
return false;
}
}
}
}

View File

@@ -1,203 +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 System.Collections.Concurrent;
using System.IO;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 传输文件Hash暂存字典
/// </summary>
public static class TransferFileHashDictionary
{
private static ConcurrentDictionary<string, UrlFileInfo> fileHashAndInfo = new ConcurrentDictionary<string, UrlFileInfo>();
private static ConcurrentDictionary<string, UrlFileInfo> filePathAndInfo = new ConcurrentDictionary<string, UrlFileInfo>();
/// <summary>
/// 字典存储文件Hash的最大数量默认为10000
/// </summary>
public static int MaxCount { get; set; } = 10000;
/// <summary>
/// 添加文件信息
/// </summary>
/// <param name="filePath"></param>
/// <param name="breakpointResume"></param>
/// <returns></returns>
public static UrlFileInfo AddFile(string filePath, bool breakpointResume = true)
{
UrlFileInfo urlFileInfo = new UrlFileInfo();
using (FileStream stream = File.OpenRead(filePath))
{
urlFileInfo.FilePath = filePath;
urlFileInfo.FileLength = stream.Length;
urlFileInfo.FileName = Path.GetFileName(filePath);
if (breakpointResume)
{
urlFileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
}
}
AddFile(urlFileInfo);
return urlFileInfo;
}
/// <summary>
/// 添加文件信息
/// </summary>
/// <param name="urlFileInfo"></param>
public static void AddFile(UrlFileInfo urlFileInfo)
{
if (urlFileInfo == null)
{
return;
}
filePathAndInfo.AddOrUpdate(urlFileInfo.FilePath, urlFileInfo, (key, oldValue) =>
{
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)
{
if (filePathAndInfo.TryRemove(item, out _))
{
break;
}
}
}
if (fileHashAndInfo.Count > MaxCount)
{
foreach (var item in fileHashAndInfo.Keys)
{
if (fileHashAndInfo.TryRemove(item, out _))
{
break;
}
}
}
}
/// <summary>
/// 清除全部
/// </summary>
public static void ClearDictionary()
{
if (filePathAndInfo == null)
{
return;
}
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>
/// <param name="filePath"></param>
/// <returns></returns>
public static bool Remove(string filePath)
{
if (filePathAndInfo == null)
{
return false;
}
return filePathAndInfo.TryRemove(filePath, out _);
}
}
}

View File

@@ -1,166 +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 System.IO;
namespace RRQMSocket.FileTransfer
{
/// <summary>
/// 文件信息类
/// </summary>
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="flags"></param>
/// <returns></returns>
public static UrlFileInfo CreateDownload(string path, TransferFlags flags)
{
UrlFileInfo fileInfo = new UrlFileInfo();
fileInfo.FilePath = path;
fileInfo.Flags = flags;
fileInfo.FileName = Path.GetFileName(path);
fileInfo.TransferType = TransferType.Download;
return fileInfo;
}
/// <summary>
/// 生成上传请求必要信息
/// </summary>
/// <param name="path"></param>
/// <param name="flags"></param>
/// <returns></returns>
public static UrlFileInfo CreateUpload(string path, TransferFlags flags)
{
UrlFileInfo fileInfo = new UrlFileInfo();
fileInfo.TransferType = TransferType.Upload;
using (FileStream stream = File.OpenRead(path))
{
fileInfo.Flags = flags;
fileInfo.FilePath = path;
if (flags.HasFlag(TransferFlags.BreakpointResume) || flags.HasFlag(TransferFlags.QuickTransfer))
{
fileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
}
fileInfo.FileLength = stream.Length;
fileInfo.FileName = Path.GetFileName(path);
}
return fileInfo;
}
/// <summary>
/// 复制
/// </summary>
/// <param name="urlFileInfo"></param>
public void CopyFrom(UrlFileInfo urlFileInfo)
{
this.FileHash = urlFileInfo.FileHash;
this.FileLength = urlFileInfo.FileLength;
this.FileName = urlFileInfo.FileName;
this.FilePath = urlFileInfo.FilePath;
}
/// <summary>
/// 判断参数是否相同
/// </summary>
/// <param name="urlFileInfo"></param>
/// <returns></returns>
public bool Equals(UrlFileInfo urlFileInfo)
{
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;
}
}
}