1
1

FileSignatureDetector.cs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using Masuit.Tools.Reflection;
  7. using Masuit.Tools.Systems;
  8. namespace Masuit.Tools.Files.FileDetector;
  9. public static class FileSignatureDetector
  10. {
  11. private static List<IDetector> Detectors { get; set; } = [];
  12. public static IReadOnlyList<IDetector> Registered => Detectors;
  13. public static void AddDetector<T>() where T : IDetector
  14. {
  15. var instance = Activator.CreateInstance<T>();
  16. AddDetector(instance);
  17. }
  18. public static void AddDetector(IDetector instance)
  19. {
  20. if (!Detectors.Contains(instance))
  21. {
  22. Detectors.Add(instance);
  23. }
  24. }
  25. static FileSignatureDetector()
  26. {
  27. var type = typeof(IDetector);
  28. foreach (var item in AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.FullName.StartsWith(["System", "Microsoft"])).SelectMany(a => a.GetLoadableExportedTypes()))
  29. {
  30. if (type.IsAssignableFrom(item) && !item.IsAbstract && !item.IsInterface && item.GetTypeInfo().DeclaredConstructors.First().GetParameters().Length == 0)
  31. {
  32. AddDetector(Activator.CreateInstance(item) as IDetector);
  33. }
  34. }
  35. }
  36. public static IDetector DetectFiletype(string filepath)
  37. {
  38. using var stream = File.OpenRead(filepath);
  39. return DetectFiletype(stream);
  40. }
  41. public static IDetector DetectFiletype(this FileInfo file)
  42. {
  43. using var stream = file.OpenRead();
  44. return DetectFiletype(stream);
  45. }
  46. public static IDetector DetectFiletype(this Stream stream)
  47. {
  48. if (stream.CanSeek)
  49. {
  50. string pre = null;
  51. IDetector foundDetector = new NoneDetector();
  52. while (true)
  53. {
  54. bool found = false;
  55. foreach (var detector in Detectors.Where(d => d.Precondition == pre))
  56. {
  57. stream.Position = 0;
  58. if (detector.Detect(stream))
  59. {
  60. found = true;
  61. foundDetector = detector;
  62. pre = detector.Extension;
  63. break;
  64. }
  65. }
  66. if (!found)
  67. {
  68. break;
  69. }
  70. }
  71. stream.Position = 0;
  72. return foundDetector;
  73. }
  74. using var ms = new PooledMemoryStream();
  75. stream.CopyTo(ms);
  76. return DetectFiletype(ms);
  77. }
  78. }